css - w3schools - Cuadrado con esquinas redondeadas y borde curvado con sangría.
html css geometric shapes (4)
Este borrador de simulacro es lo más cercano que pude a CSS puro, pero aún requiere un div anidado. Necesitaría ajustar el tamaño / radio para los círculos antes / después.
div {
position: absolute;
top: 100px;
left: 100px;
width: 100px;
height: 100px;
border: 4px solid purple;
border-radius: 30px;
//overflow: hidden;
box-sizing: border-box;
&:before {
position: absolute;
top: -4px;
left: -94px;
content: '' '';
width: 100px;
height: 100px;
border: 4px solid purple;
border-radius: 50px;
box-sizing: border-box;
background-color: white;
clip: rect(0px, 100px, 100px, 90px);
}
&:after {
position: absolute;
top: -4px;
right: -94px;
content: '' '';
width: 100px;
height: 100px;
border: 4px solid purple;
border-radius: 50px;
box-sizing: border-box;
background-color: white;
clip: rect(0px, 10px, 100px, 0px);
}
}
div > div {
position: absolute;
top: -4px;
left: -4px;
transform: rotate(90deg);
border-color: transparent;
}
Otro enfoque de CSS puro para crear este borde sería hacer uso de la propiedad de border-image
de border-image
. Todo lo que se requiere es crear una imagen con la forma de borde requerida y establecerla en un elemento utilizando la propiedad border-image-source
.
.shape.large {
height: 300px;
width: 300px;
border-image-source: url(http://i.stack.imgur.com/Qkh6A.png);
border-image-width: 34px; /* the width of the border portions in the image - refer to image at the end of the answer for the exact portion details*/
border-image-slice: 34; /* equal to border-image-width */
border-width: 34px; /* equal to border-image-width */
}
.shape.small {
height: 100px;
width: 100px;
border-image-source: url(http://i.stack.imgur.com/Mra4B.png);
border-image-width: 14px;
border-image-slice: 14;
border-width: 14px;
}
.shape.small.fill {
background: aliceblue content-box;
border-image-source: url(http://i.stack.imgur.com/Ovj03.png);
border-width: 14px;
}
/* Just for demo */
body {
background: url(http://lorempixel.com/800/800/abstract/2);
}
.shape.small {
float: left;
}
.shape.large {
clear: both;
}
<div class=''shape small''>Some content</div>
<div class=''shape small fill''>Some content</div>
<div class=''shape large''>Some content</div>
En la actualidad, este método definitivamente no es muy ventajoso en comparación con SVG, pero es una opción y, en mi opinión, es mejor que los otros enfoques de CSS que son posibles.
Las ventajas de este enfoque son:
- Código muy mínimo y de baja complejidad.
- Mejor control sobre las curvas y sus radios (como con SVG) porque la imagen con la curvatura de borde requerida se puede crear por separado.
- Se puede colocar encima de una imagen o un fondo degradado.
- Puede hacerse para degradarse con gracia (en un borde cuadrado sólido) en el navegador que no lo admite.
Los inconvenientes son:
- El contenedor sigue siendo un cuadrado, por lo que los efectos de
hover
no se limitarán a los límites de la forma, a diferencia de SVG. - Es posible agregar relleno de color sólido a la forma (utilizando una versión rellena de la imagen), pero agregar un degradado o relleno de imagen es complicado porque los bordes aún son bloques (es decir, hay áreas transparentes a ambos lados de las curvas).
- La salida es sensible, pero a medida que las dimensiones aumentan o disminuyen más allá de un umbral, la forma comienza a verse un poco comprimida o estirada. Por lo tanto, esto es más adecuado para el diseño basado en puntos de ruptura.
- El soporte del navegador no es malo pero tampoco es genial. Funciona en Chrome, Firefox, Safari, Opera e IE11 +.
Cálculo del ancho de la imagen del borde:
El ancho o alto del área del borde (que se convierte en el border-image-width
del border-image-width
) no es más que el ancho de la parte resaltada en la imagen de abajo.
SVG es probablemente el camino a seguir, pero aquí hay una aproximación bastante cercana en CSS puro. Se podría hacer aún mejor al aumentar el tamaño de los círculos exteriores.
#middle {
width: 96px;
height: 96px;
border-radius: 10px;
background-color: green;
border: 2px solid #8A6EF1;
}
.outside {
width: 100px;
height: 100px;
position: relative;
overflow: hidden;
margin: 0;
padding: 0;
}
.cutout {
width: 96px;
height: 96px;
border-radius: 50%;
background-color: white;
border: 2px solid #8A6EF1;
}
#top {
top: -100px;
height: 10px;
}
#right {
top: -110px;
left: 90px;
width: 10px;
}
#bottom {
top: -120px;
height: 10px;
}
#left {
top: -220px;
width: 10px;
}
#top > .cutout {
margin-top: -90px;
}
#left > .cutout {
margin-left: -90px;
}
<div id="wrapper">
<div id="middle">
</div>
<div id="top" class="outside">
<div class="cutout">
</div>
</div>
<div id="right" class="outside">
<div class="cutout">
</div>
</div>
<div id="bottom" class="outside">
<div class="cutout">
</div>
</div>
<div id="left" class="outside">
<div class="cutout">
</div>
</div>
</div>
Teniendo en cuenta la molestia y la cantidad de código necesaria para alinear curvas dobles con CSS , SVG parece mucho más apropiado . Algunas otras razones para ir para svg aquí son:
- Control del recorrido (color, ancho, curva ...).
- Controla el relleno con un color liso, degradado o imagen.
- menos código
- puede mostrarlo sobre un fondo no liso (degradado o imagen)
- mantener los límites de la forma para las interacciones del usuario (desplazar, hacer clic ...)
Aquí hay un ejemplo básico que usa un svg en línea con un elemento de ruta .
Las curvas se dibujan con curvas de Bezier cúbico :
svg{width:30%;}
<svg viewbox="0 0 10 10">
<path d="M1.5 0.5 Q5 1 8.5 0.5 Q9.5 0.5 9.5 1.5 Q9 5 9.5 8.5 Q9.5 9.5 8.5 9.5 Q5 9 1.5 9.5 Q0.5 9.5 0.5 8.5 Q1 5 0.5 1.5 Q0.5 0.5 1.5 0.5z"
fill="none" stroke-width="0.2" stroke="#8A6FF2" />
</svg>