Hay muchas formas de crear la forma con un borde inclinado solo en un lado.
Los siguientes métodos no pueden admitir tamaños dinámicos como ya se mencionó en la pregunta:
- Método del triángulo de borde con valores de píxeles para
border-width
.
- Degradados lineales con la sintaxis del ángulo (como 45 grados, 30 grados, etc.).
Los métodos que pueden admitir tamaños dinámicos se describen a continuación.
Método 1 - SVG
( Compatibilidad del navegador )
SVG se puede usar para producir la forma usando polygon
s o path
s. El siguiente fragmento hace uso de polygon
. Cualquier contenido de texto requerido se puede colocar encima de la forma.
$(document).ready(function() {
$('#increasew-vector').on('click', function() {
$('.vector').css({
'width': '150px',
'height': '100px'
});
});
$('#increaseh-vector').on('click', function() {
$('.vector').css({
'width': '100px',
'height': '150px'
});
});
$('#increaseb-vector').on('click', function() {
$('.vector').css({
'width': '150px',
'height': '150px'
});
});
})
div {
float: left;
height: 100px;
width: 100px;
margin: 20px;
color: beige;
transition: all 1s;
}
.vector {
position: relative;
}
svg {
position: absolute;
margin: 10px;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
z-index: 0;
}
polygon {
fill: tomato;
}
.vector > span {
position: absolute;
display: block;
padding: 10px;
z-index: 1;
}
.vector.top > span{
height: 50%;
width: 100%;
top: calc(40% + 5px);
left: 5px;
}
.vector.bottom > span{
height: 50%;
width: 100%;
top: 5px;
left: 5px;
}
.vector.left > span{
width: 50%;
height: 100%;
left: 50%;
top: 5px;
}
.vector.right > span{
width: 50%;
height: 100%;
left: 5px;
top: 5px;
}
body {
background: radial-gradient(circle at 50% 50%, aliceblue, steelblue);
}
polygon:hover, span:hover + svg > polygon{
fill: steelblue;
}
.btn-container {
position: absolute;
top: 0px;
right: 0px;
width: 150px;
}
button {
width: 150px;
margin-bottom: 10px;
}
.vector.left{
clear: both;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="vector bottom">
<span>Some content</span>
<svg viewBox="0 0 40 100" preserveAspectRatio="none">
<polygon points="0,0 40,0 40,100 0,60" />
</svg>
</div>
<div class="vector top">
<span>Some content</span>
<svg viewBox="0 0 40 100" preserveAspectRatio="none">
<polygon points="0,40 40,0 40,100 0,100" />
</svg>
</div>
<div class="vector left">
<span>Some content</span>
<svg viewBox="0 0 40 100" preserveAspectRatio="none">
<polygon points="0,0 40,0 40,100 20,100" />
</svg>
</div>
<div class="vector right">
<span>Some content</span>
<svg viewBox="0 0 40 100" preserveAspectRatio="none">
<polygon points="0,0 20,0 40,100 0,100" />
</svg>
</div>
<div class='btn-container'>
<button id="increasew-vector">Increase Width</button>
<button id="increaseh-vector">Increase Height</button>
<button id="increaseb-vector">Increase Both</button>
</div>
Pros
- SVG está diseñado para producir gráficos escalables y puede funcionar bien con todos los cambios de dimensión.
- Los bordes y el efecto de desplazamiento se pueden lograr con una sobrecarga de codificación mínima.
- También se puede proporcionar una imagen o un fondo degradado a la forma.
Contras
- El soporte del navegador es probablemente el único inconveniente porque IE8- no es compatible con SVG, pero eso se puede mitigar usando bibliotecas como Raphael y también VML. Además, el soporte del navegador no es de ninguna manera peor que las otras opciones.
Método 2 - Fondo degradado
( Compatibilidad del navegador )
Los degradados lineales aún se pueden usar para producir la forma, pero no con ángulos como se menciona en la pregunta. Tenemos que usar la to [side] [side]
sintaxis (gracias a vals ) en lugar de especificar ángulos. Cuando se especifican los lados, los ángulos de degradado se ajustan automáticamente según las dimensiones del contenedor.
$(document).ready(function() {
$('#increasew-gradient').on('click', function() {
$('.gradient').css({
'height': '100px',
'width': '150px'
});
});
$('#increaseh-gradient').on('click', function() {
$('.gradient').css({
'height': '150px',
'width': '100px'
});
});
$('#increaseb-gradient').on('click', function() {
$('.gradient').css({
'height': '150px',
'width': '150px'
});
});
})
div {
float: left;
height: 100px;
width: 100px;
margin: 10px 20px;
color: beige;
transition: all 1s;
}
.gradient{
position: relative;
}
.gradient.bottom {
background: linear-gradient(to top right, transparent 50%, tomato 50%) no-repeat, linear-gradient(to top right, transparent 0.1%, tomato 0.1%) no-repeat;
background-size: 100% 40%, 100% 60%;
background-position: 0% 100%, 0% 0%;
}
.gradient.top {
background: linear-gradient(to bottom right, transparent 50%, tomato 50%) no-repeat, linear-gradient(to bottom right, transparent 0.1%, tomato 0.1%) no-repeat;
background-size: 100% 40%, 100% 60%;
background-position: 0% 0%, 0% 100%;
}
.gradient.left {
background: linear-gradient(to top right, transparent 50%, tomato 50%) no-repeat, linear-gradient(to top right, transparent 0.1%, tomato 0.1%) no-repeat;
background-size: 40% 100%, 60% 100%;
background-position: 0% 0%, 100% 0%;
}
.gradient.right {
background: linear-gradient(to top left, transparent 50%, tomato 50%) no-repeat, linear-gradient(to top left, transparent 0.1%, tomato 0.1%) no-repeat;
background-size: 40% 100%, 60% 100%;
background-position: 100% 0%, 0% 0%;
}
.gradient span{
position: absolute;
}
.gradient.top span{
top: calc(40% + 5px);
left: 5px;
height: 50%;
}
.gradient.bottom span{
top: 5px;
left: 5px;
height: 50%;
}
.gradient.left span{
left: 40%;
top: 5px;
width: 50%;
}
.gradient.right span{
left: 5px;
top: 5px;
width: 50%;
}
body {
background: radial-gradient(circle at 50% 50%, aliceblue, steelblue);
}
.btn-container {
position: absolute;
top: 0px;
right: 0px;
width: 150px;
}
button {
width: 150px;
margin-bottom: 10px;
}
.gradient.left{
clear:both;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="gradient bottom"><span>Some content</span>
</div>
<div class="gradient top"><span>Some content</span>
</div>
<div class="gradient left"><span>Some content</span>
</div>
<div class="gradient right"><span>Some content</span>
</div>
<div class='btn-container'>
<button id="increasew-gradient">Increase Width</button>
<button id="increaseh-gradient">Increase Height</button>
<button id="increaseb-gradient">Increase Both</button>
</div>
Pros
- La forma se puede lograr y mantener incluso si las dimensiones del contenedor son dinámicas.
- El efecto de desplazamiento se puede agregar cambiando el color del degradado.
Contras
- El efecto de desplazamiento se activará incluso cuando el cursor esté fuera de la forma pero dentro del contenedor.
- Agregar bordes requeriría manipulaciones de degradado complicadas.
- Los degradados son conocidos por producir esquinas irregulares cuando el ancho (o alto) es muy grande.
- No se pueden utilizar fondos de imagen en la forma.
Método 3 - Transformaciones sesgadas
( Compatibilidad del navegador )
En este método, se agrega un pseudo-elemento, sesgado y posicionado de tal manera que parezca que uno de los bordes está inclinado / en ángulo. Si el borde superior o inferior está inclinado, el sesgo debe estar a lo largo del eje Y, de lo contrario el la rotación debe ser a lo largo del eje X. El transform-origin
debe tener el lado opuesto al lado inclinado.
$(document).ready(function() {
$('#increasew-skew').on('click', function() {
$('.skew').css({
'height': '100px',
'width': '150px'
});
});
$('#increaseh-skew').on('click', function() {
$('.skew').css({
'height': '150px',
'width': '100px'
});
});
$('#increaseb-skew').on('click', function() {
$('.skew').css({
'height': '150px',
'width': '150px'
});
});
})
div {
float: left;
height: 100px;
width: 100px;
margin: 50px;
color: beige;
transition: all 1s;
}
.skew {
padding: 10px;
position: relative;
background: tomato;
}
.skew:after {
position: absolute;
content: '';
background: inherit;
z-index: -1;
}
.skew.bottom:after,
.skew.top:after {
width: 100%;
height: 60%;
}
.skew.left:after,
.skew.right:after {
height: 100%;
width: 60%;
}
.skew.bottom:after {
bottom: 0px;
left: 0px;
transform-origin: top left;
transform: skewY(22deg);
}
.skew.top:after {
top: 0px;
left: 0px;
transform-origin: top left;
transform: skewY(-22deg);
}
.skew.left:after {
top: 0px;
left: 0px;
transform-origin: bottom left;
transform: skewX(22deg);
}
.skew.right:after {
top: 0px;
right: 0px;
transform-origin: bottom right;
transform: skewX(-22deg);
}
.skew:hover {
background: steelblue;
}
body {
background: radial-gradient(circle at 50% 50%, aliceblue, steelblue);
}
.skew.bottom {
margin-top: 10px;
}
.skew.left {
clear: both;
}
.btn-container {
position: absolute;
top: 0px;
right: 0px;
width: 150px;
}
button {
width: 150px;
margin-bottom: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="skew bottom">Some content</div>
<div class="skew top">Some content</div>
<div class="skew left">Some content</div>
<div class="skew right">Some content</div>
<div class='btn-container'>
<button id="increasew-skew">Increase Width</button>
<button id="increaseh-skew">Increase Height</button>
<button id="increaseb-skew">Increase Both</button>
</div>
Pros
- La forma se puede lograr incluso con bordes.
- El efecto de desplazamiento se limitará a la forma.
Contras
- Las dimensiones deben aumentar proporcionalmente para que se mantenga la forma porque cuando un elemento está sesgado, su desplazamiento en el eje Y aumenta a medida que
width
aumenta y viceversa (intente aumentar el width
a 200px
en el fragmento). Puede encontrar más información sobre esto aquí .
Método 4 - Transformaciones de perspectiva
( Compatibilidad del navegador )
En este método, el contenedor principal se gira a lo largo del eje X o Y con un poco de perspectiva. Establecer el valor apropiado en transform-origin
produciría un borde inclinado en un solo lado.
Si el lado superior o inferior está inclinado, la rotación debe ser a lo largo del eje Y, de lo contrario, la rotación debe ser a lo largo del eje X. El transform-origin
debe tener el lado opuesto al lado inclinado.
$(document).ready(function() {
$('#increasew-rotate').on('click', function() {
$('.rotate').css({
'height': '100px',
'width': '150px'
});
});
$('#increaseh-rotate').on('click', function() {
$('.rotate').css({
'height': '150px',
'width': '100px'
});
});
$('#increaseb-rotate').on('click', function() {
$('.rotate').css({
'height': '150px',
'width': '150px'
});
});
})
div {
float: left;
height: 100px;
width: 100px;
margin: 50px;
color: beige;
transition: all 1s;
}
.rotate {
position: relative;
width: 100px;
background: tomato;
}
.rotate.bottom {
transform-origin: top;
transform: perspective(10px) rotateY(-2deg);
}
.rotate.top {
transform-origin: bottom;
transform: perspective(10px) rotateY(-2deg);
}
.rotate.left {
transform-origin: right;
transform: perspective(10px) rotateX(-2deg);
}
.rotate.right {
transform-origin: left;
transform: perspective(10px) rotateX(-2deg);
}
.rotate span {
position: absolute;
display: block;
top: 0px;
right: 0px;
width: 50%;
height: 100%;
}
.rotate.bottom span {
padding: 10px;
transform-origin: top;
transform: perspective(10px) rotateY(2deg);
}
.rotate.top span {
padding: 20px;
transform-origin: bottom;
transform: perspective(20px) rotateY(2deg);
}
.rotate.left span {
padding: 10px;
transform-origin: right;
transform: perspective(10px) rotateX(2deg);
}
.rotate.right span {
padding: 0px 30px;
transform-origin: left;
transform: perspective(10px) rotateX(2deg);
}
.rotate:hover {
background: steelblue;
}
body {
background: radial-gradient(circle at 50% 50%, aliceblue, steelblue);
}
.rotate.left{
clear:both;
}
.btn-container {
position: absolute;
top: 0px;
right: 0px;
width: 150px;
}
button {
width: 150px;
margin-bottom: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="rotate bottom"><span>Some content</span>
</div>
<div class="rotate top"><span>Some content</span>
</div>
<div class="rotate left"><span>Some content</span>
</div>
<div class="rotate right"><span>Some content</span>
</div>
<div class='btn-container'>
<button id="increasew-rotate">Increase Width</button>
<button id="increaseh-rotate">Increase Height</button>
<button id="increaseb-rotate">Increase Both</button>
</div>
Pros
- La forma se puede lograr con bordes.
- Las dimensiones no necesitan aumentar proporcionalmente para mantener la forma.
Contras
- El contenido también se rotará y, por lo tanto, tendrá que girar en sentido contrario para que parezca normal.
- Colocar el texto será tedioso si las dimensiones no son estáticas.
Método 5 - Ruta del clip CSS
( Compatibilidad del navegador )
En este método, el contenedor principal se recorta en la forma requerida utilizando un polígono. Los puntos del polígono deben modificarse según el lado donde se requiera el borde inclinado.
$(document).ready(function() {
$('#increasew-clip').on('click', function() {
$('.clip-path').css({
'height': '100px',
'width': '150px'
});
});
$('#increaseh-clip').on('click', function() {
$('.clip-path').css({
'height': '150px',
'width': '100px'
});
});
$('#increaseb-clip').on('click', function() {
$('.clip-path').css({
'height': '150px',
'width': '150px'
});
});
})
.clip-path {
position: relative;
float: left;
margin: 20px;
height: 100px;
width: 100px;
background: tomato;
padding: 4px;
transition: all 1s;
}
.clip-path.bottom {
-webkit-clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 60%);
}
.clip-path.top {
-webkit-clip-path: polygon(0% 40%, 100% 0%, 100% 100%, 0% 100%);
}
.clip-path.left {
-webkit-clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 40% 100%);
}
.clip-path.right {
-webkit-clip-path: polygon(0% 0%, 60% 0%, 100% 100%, 0% 100%);
}
.clip-path .content {
position: absolute;
content: '';
height: calc(100% - 10px);
width: calc(100% - 8px);
background: bisque;
}
.clip-path.bottom .content {
-webkit-clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 60%);
}
.clip-path.top .content {
-webkit-clip-path: polygon(0% 40%, 100% 0%, 100% 100%, 0% 100%);
}
.clip-path .content.img {
top: 6px;
background: url(http://lorempixel.com/250/250);
background-size: 100% 100%;
}
body {
background: radial-gradient(circle at 50% 50%, aliceblue, steelblue);
}
.clip-path.left {
clear: both;
}
.clip-path:hover {
background: gold;
}
.btn-container {
position: absolute;
top: 0px;
right: 0px;
margin: 20px;
width: 150px;
}
button {
width: 150px;
margin-bottom: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="clip-path bottom">
<div class="content">abcd</div>
</div>
<div class="clip-path top">
<div class="content img"></div>
</div>
<div class="clip-path left"></div>
<div class="clip-path right"></div>
<div class='btn-container'>
<button id="increasew-clip">Increase Width</button>
<button id="increaseh-clip">Increase Height</button>
<button id="increaseb-clip">Increase Both</button>
</div>
Pros
- La forma se puede mantener incluso cuando se cambia el tamaño del contenedor de forma dinámica.
- El efecto de desplazamiento estará perfectamente restringido dentro de los bordes de la forma.
- La imagen también se puede utilizar como fondo para la forma.
Contras
- El soporte del navegador es muy deficiente en la actualidad.
- Se pueden agregar bordes colocando un elemento absolutamente posicionado en la parte superior de la forma y dándole el clip necesario, pero más allá de un punto, no encaja bien cuando se redimensiona dinámicamente.
Método 6 - Lienzo
( Compatibilidad del navegador )
Canvas también se puede utilizar para producir la forma dibujando trazados. El siguiente fragmento tiene una demostración. Cualquier contenido de texto requerido se puede colocar encima de la forma.
window.onload = function() {
var canvasEls = document.getElementsByTagName('canvas');
for (var i = 0; i < canvasEls.length; i++) {
paint(canvasEls[i]);
}
function paint(canvas) {
var ctx = canvas.getContext('2d');
ctx.beginPath();
if (canvas.className == 'bottom') {
ctx.moveTo(0, 0);
ctx.lineTo(250, 0);
ctx.lineTo(250, 100);
ctx.lineTo(0, 60);
} else if (canvas.className == 'top') {
ctx.moveTo(0, 40);
ctx.lineTo(250, 0);
ctx.lineTo(250, 100);
ctx.lineTo(0, 100);
} else if (canvas.className == 'left') {
ctx.moveTo(0, 0);
ctx.lineTo(250, 0);
ctx.lineTo(250, 100);
ctx.lineTo(60, 100);
} else if (canvas.className == 'right') {
ctx.moveTo(0, 0);
ctx.lineTo(190, 0);
ctx.lineTo(250, 100);
ctx.lineTo(0, 100);
}
ctx.closePath();
ctx.lineCap = 'round';
ctx.fillStyle = 'tomato';
ctx.fill();
}
$('#increasew-canvas').on('click', function() {
$('.container').css({
'width': '150px',
'height': '100px'
});
});
$('#increaseh-canvas').on('click', function() {
$('.container').css({
'width': '100px',
'height': '150px'
});
});
$('#increaseb-canvas').on('click', function() {
$('.container').css({
'width': '150px',
'height': '150px'
});
});
};
.container {
float: left;
position: relative;
height: 100px;
width: 100px;
margin: 20px;
color: beige;
transition: all 1s;
}
canvas {
height: 100%;
width: 100%;
}
.container > span {
position: absolute;
top: 5px;
left: 5px;
padding: 5px;
}
.top + span {
top: 40%;
}
.left + span {
left: 40%;
}
body {
background: radial-gradient(circle at 50% 50%, aliceblue, steelblue);
}
.btn-container {
position: absolute;
top: 0px;
right: 0px;
width: 150px;
}
button {
width: 150px;
margin-bottom: 10px;
}
div:nth-of-type(3) {
clear: both;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="container">
<canvas height="100px" width="250px" class="bottom"></canvas> <span>Some content</span>
</div>
<div class="container">
<canvas height="100px" width="250px" class="top"></canvas> <span>Some content</span>
</div>
<div class="container">
<canvas height="100px" width="250px" class="left"></canvas> <span>Some content</span>
</div>
<div class="container">
<canvas height="100px" width="250px" class="right"></canvas> <span>Some content</span>
</div>
<div class='btn-container'>
<button id="increasew-canvas">Increase Width</button>
<button id="increaseh-canvas">Increase Height</button>
<button id="increaseb-canvas">Increase Both</button>
</div>
Pros
- La forma se puede lograr y mantener incluso si las dimensiones del contenedor son dinámicas. También se pueden agregar bordes.
- El efecto de desplazamiento se puede restringir dentro de los límites de la forma mediante el
pointInpath
método.
- También se puede proporcionar una imagen o un fondo degradado a la forma.
- Mejor opción si se necesitan efectos de animación en tiempo real, ya que no requiere manipulación DOM.
Contras
- El lienzo se basa en ráster y, por lo tanto, los bordes en ángulo se pixelarán o difuminarán cuando se escalen más allá de un punto * .
* - Evitar la pixelación necesitaría volver a pintar la forma cada vez que se cambia el tamaño de la ventana gráfica. Hay un ejemplo de esto aquí, pero es una sobrecarga.
Mi solución está inspirada en el llamado Método 7 - Unidades de ventana de Andrea Ligios, arriba en esta página.
También utilicé la unidad "horizontal" para la altura (
height:10vw
) para mantener las proporciones dadas en el trapezoide al cambiar el tamaño del ancho de la ventana de navegación. Podríamos llamar a esto Método 7b - Ancho de la ventana gráfica .Además, el uso de dos
div
s anidados , en lugar de uno y el:after
selector, permite un mejor ajuste de los estilos de contenido de texto, en mi opinión (por ejemplotext-align
, etc.)..dtrapz { position: relative; margin: 10px 40vw; width: 0; height: 10vw; border: none; border-right: 20vw solid #f22; border-bottom: 5vw solid transparent; } .dtcont { position: absolute; width: 20vw; height: 10vw; text-align: center; color: #fff;/* just aesthetic */ }
<div class="dtrapz"> <div class="dtcont">Some content</div> </div>
fuente