Carré avec des coins arrondis et décalés courbe frontière
je me demandais s'il était possible de faire un carré avec des coins ronds et une bordure dentelée en CSS pur.
Actuellement j'ai ceci:
#custom-square {
position: relative;
display: block;
width: 75px;
height: 75px;
border: 2px solid #8A6EF1;
border-radius: 10px;
background-color: white;
}
4 réponses
compte tenu de la dispute et de la quantité de code nécessaire pour aligner double courbes avec CSS,SVG semble le moyen le plus approprié. Voici quelques autres raisons d'opter pour svg:
- contrôle du chemin (couleur, largeur, courbe...)
- contrôlez le remplissage avec une couleur claire, un gradient ou une image
- moins de code
- vous pouvez l'afficher sur un fond non simple (gradient ou image)
- maintenir les limites de la forme des interactions utilisateur (hover, click...)
voici un exemple de base utilisant un inline svg avec un chemin d'accès de l'élément.
Les courbes sont tracées avec courbes de Bézier cubique:
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>
une autre approche purement CSS pour créer cette frontière serait d'utiliser border-image
propriété. Tout ce qui est requis est de créer une image avec la forme de bordure requise et de la placer sur un élément en utilisant le border-image-source
propriété.
.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>
actuellement cette méthode est certainement pas très avantageux par rapport à SVG mais c'est une option et à mon avis c'est mieux que les autres approches CSS uniquement qui sont possibles.
les avantages de cette approche sont les suivants:
- code très minime et de faible complexité.
- meilleur contrôle des courbes et de leurs rayons (comme avec SVG) car l'image avec la courbure de bordure requise peut être créée séparément.
- peut être placé au-dessus d'une image ou d'un fond dégradé.
- peut être fait pour se dégrader gracieusement (dans une bordure carrée solide) dans les navigateurs qui ne supportent pas il.
inconvénients:
- Le conteneur est toujours un carré et donc
hover
les effets ne seront pas limités aux limites de la forme contrairement à SVG. - il est possible d'Ajouter un remplissage de couleur unie à la forme (en utilisant une version remplie de l'image) mais ajouter un remplissage de gradient ou d'image est délicat parce que les bordures sont toujours des blocs (c'est-à-dire qu'il y a des zones transparentes de chaque côté des courbes).
- le la sortie est réactive mais au fur et à mesure que les dimensions augmentent ou diminuent au-delà d'un seuil, la forme commence à paraître un peu comprimée ou étirée. Donc, c'est plus approprié pour la conception basée sur le point de rupture.
- support du navigateur n'est pas mauvais mais n'est pas la grande forme non plus. Il fonctionne en Chrome, Firefox, Safari, Opera et IE11+.
calcul de la largeur de L'image de bordure:
la largeur ou La hauteur de la zone frontalière, qui devient le border-image-width
) rien que la largeur de la portion mise en évidence dans l'image ci-dessous.
cette maquette de projet est aussi proche que j'ai pu l'obtenir à CSS pur, mais nécessite toujours une cession imbriquée. Vous devez modifier le dimensionnement / rayon pour les cercles avant / aprè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;
}
SVG est probablement la voie à suivre ici, Mais voici une approximation assez proche dans CSS pur. Il pourrait être encore mieux en augmentant la taille des cercles extérieurs.
#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>