Contrôlez la longueur et la distance entre les traits de la bordure en pointillés

124

Est-il possible de contrôler la longueur et la distance entre les traits de bordure en pointillés dans CSS?

Cet exemple ci-dessous s'affiche différemment selon les navigateurs:

div {
  border: dashed 4px #000;
  padding: 20px;
  display: inline-block;
}
<div>I have a dashed border!</div>

De grandes différences: IE 11 / Firefox / Chrome

Bordure IE 11Bordure FirefoxBordure chromée

Existe-t-il des méthodes permettant de mieux contrôler l'apparence des bordures en pointillés?

AntonAL
la source

Réponses:

157

La valeur de la propriété native de la bordure en pointillés n'offre pas de contrôle sur les tirets eux-mêmes ... alors apportez la border-imagepropriété!

Brassez votre propre frontière avec border-image

Compatibilité : il offre une excellente prise en charge des navigateurs (IE 11 et tous les navigateurs modernes). Une bordure normale peut être définie comme solution de secours pour les navigateurs plus anciens.

Créons ces

Ces bordures afficheront exactement le même cross-browser!

Exemple d'objectif Exemple d'objectif avec des écarts plus larges

Étape 1 - Créez une image appropriée

Cet exemple mesure 15 pixels de large sur 15 pixels de haut et les espaces sont actuellement de 5 px de large. C'est un .png avec transparence.

Voici à quoi cela ressemble dans Photoshop lorsque vous zoomez:

Exemple de fond d'image de bordure agrandi

Voici à quoi ressemble la mise à l'échelle:

Exemple de bordure d'image d'arrière-plan Taille réelle

Contrôle de l'écart et de la longueur de course

Pour créer des espaces ou des traits plus larges / plus courts, élargissez / réduisez les espaces ou les traits de l'image.

Voici une image avec des espaces plus larges de 10 pixels:

Des écarts plus importants correctement mis à l'échelle = Des écarts plus importants à l'échelle

Étape 2 - Créez le CSS - cet exemple nécessite 4 étapes de base

  1. Définissez la source de l'image de la bordure :

    border-image-source:url("http://i.stack.imgur.com/wLdVc.png");  
  2. Facultatif - Définissez la largeur de l'image de la bordure :

    border-image-width: 1;

    La valeur par défaut est 1. Elle peut également être définie avec une valeur de pixel, une valeur de pourcentage ou comme un autre multiple (1x, 2x, 3x, etc.). Cela remplace tout border-widthensemble.

  3. Définissez le border-image-slice :

    Dans cet exemple, l'épaisseur des bordures supérieure, droite, inférieure et gauche des images est de 2 pixels, et il n'y a pas d'espace en dehors, donc notre valeur de tranche est 2:

    border-image-slice: 2; 

    Les tranches ressemblent à ceci, à 2 pixels du haut, de la droite, du bas et de la gauche:

    Exemple de tranches

  4. Définissez le border-image-repeat :

    Dans cet exemple, nous voulons que le motif se répète uniformément autour de notre div. Nous choisissons donc:

    border-image-repeat: round;

Rédaction de sténographie

Les propriétés ci-dessus peuvent être définies individuellement ou en abrégé en utilisant border-image :

border-image: url("http://i.stack.imgur.com/wLdVc.png") 2 round;

Exemple complet

Notez le border: dashed 4px #000repli. Les navigateurs non compatibles recevront cette bordure.

.bordered {
  display: inline-block;
  padding: 20px;
  /* Fallback dashed border
     - the 4px width here is overwritten with the border-image-width (if set)
     - the border-image-width can be omitted below if it is the same as the 4px here
  */
  border: dashed 4px #000;
  
  /* Individual border image properties */
  border-image-source: url("http://i.stack.imgur.com/wLdVc.png");
  border-image-slice: 2;
  border-image-repeat: round;  
  
  /* or use the shorthand border-image */
  border-image: url("http://i.stack.imgur.com/wLdVc.png") 2 round;
}


/*The border image of this one creates wider gaps*/
.largeGaps {
  border-image-source: url("http://i.stack.imgur.com/LKclP.png");
  margin: 0 20px;
}
<div class="bordered">This is bordered!</div>

<div class="bordered largeGaps">This is bordered and has larger gaps!</div>

monsieurManSam
la source
Notez que vous devez spécifier border-style: solid(ou quelque chose de similaire) si vous omettez le remplacement.
Robbendebiene
Cette solution ne fonctionne pas avec l'attribut 'border-color'
Michael Rovinsky
102

En plus de la border-imagepropriété, il existe quelques autres façons de créer une bordure en pointillés avec un contrôle sur la longueur du trait et la distance qui les sépare. Ils sont décrits ci-dessous:

Méthode 1: utilisation de SVG

Nous pouvons créer la bordure en pointillés en utilisant pathun polygonélément ou et en définissant la stroke-dasharraypropriété. La propriété prend deux paramètres où l'un définit la taille du tiret et l'autre détermine l'espace entre eux.

Avantages:

  1. Les SVG par nature sont des graphiques évolutifs et peuvent s'adapter à toutes les dimensions de conteneurs.
  2. Peut très bien fonctionner même s'il y a un border-radiusimpliqué. Nous aurions juste remplacer le pathpar un circlecomme dans cette réponse (ou) convertir le pathen cercle.
  3. Le support du navigateur pour SVG est assez bon et une solution de secours peut être fournie en utilisant VML pour IE8-.

Les inconvénients:

  1. Lorsque les dimensions du conteneur ne changent pas proportionnellement, les chemins ont tendance à être mis à l'échelle, ce qui entraîne un changement de taille du tiret et de l'espace entre eux (essayez de survoler la première case de l'extrait de code). Cela peut être contrôlé en ajoutant vector-effect='non-scaling-stroke'(comme dans la deuxième case) mais la prise en charge du navigateur pour cette propriété est nulle dans IE.


Méthode 2: utiliser des dégradés

Nous pouvons utiliser plusieurs linear-gradientimages d'arrière - plan et les positionner de manière appropriée pour créer un effet de bordure en pointillé. Cela peut également être fait avec un repeating-linear-gradientmais il n'y a pas beaucoup d'amélioration en raison de l'utilisation d'un dégradé répétitif car nous avons besoin que chaque dégradé se répète dans une seule direction.

Avantages:

  1. Évolutif et peut s'adapter même si les dimensions du conteneur sont dynamiques.
  2. N'utilise pas de pseudo-éléments supplémentaires, ce qui signifie qu'ils peuvent être mis de côté pour toute autre utilisation potentielle.

Les inconvénients:

  1. La prise en charge par le navigateur des dégradés linéaires est comparativement plus faible et c'est interdit si vous souhaitez prendre en charge IE 9-. Même les bibliothèques comme CSS3 PIE ne prennent pas en charge la création de motifs de dégradés dans IE8-.
  2. Ne peut pas être utilisé lorsque border-radiusest impliqué car les arrière-plans ne se courbent pas en fonction de border-radius. Ils sont coupés à la place.

Méthode 3: Ombres de boîte

Nous pouvons créer une petite barre (en forme de tiret) à l'aide de pseudo-éléments, puis en créer plusieurs box-shadowversions pour créer une bordure comme dans l'extrait ci-dessous.

Si le tiret est de forme carrée, un seul pseudo-élément suffirait, mais s'il s'agit d'un rectangle, nous aurions besoin d'un pseudo-élément pour les bordures haut + bas et un autre pour les bordures gauche + droite. En effet, la hauteur et la largeur du tiret sur la bordure supérieure seront différentes de celles de gauche.

Avantages:

  1. Les dimensions du tableau de bord sont contrôlables en modifiant les dimensions du pseudo-élément. L'espacement est contrôlable en modifiant l'espace entre chaque ombre.
  2. Un effet très unique peut être produit en ajoutant une couleur différente pour chaque ombre de boîte.

Les inconvénients:

  1. Puisque nous devons définir manuellement les dimensions du tiret et l'espacement, cette approche n'est pas bonne lorsque les dimensions de la boîte parent sont dynamiques.
  2. IE8 et les versions antérieures ne prennent pas en charge l'ombre de boîte . Cependant, cela peut être surmonté en utilisant des bibliothèques comme CSS3 PIE.
  3. Peut être utilisé avec border-radiusmais les positionner serait très difficile à trouver des points sur un cercle (et peut-être même transform).

Harry
la source
Si vous allez utiliser la solution svg, je vous conseille d'ajouter pointer-events:noneà svg afin de pouvoir interagir avec le contenu.
Sodj
Merveilleuse réponse.
Déviance
22

Bref: non, ce n'est pas le cas. Vous devrez plutôt travailler avec des images.

Jambon Vocke
la source
5
cette réponse est obsolète en 2018
godblessstrawberry
2
@WilliamHampshire J'irais avec cette technique youtu.be/vs34f9FiHps?t=779 mais vérifiez la réponse acceptée, vous aimerez peut-être mieux d'autres solutions
godblessstrawberry
1
@godblessstrawberry Merci !! Mais c'est en utilisant SVG, donc toujours pas en utilisant juste css ...
Kyle Krzeski
1
@WilliamHampshire, il y a une solution d'ombre de boîte dans le fil Je voulais dire réponse de Harry
godblessstrawberry
@godblessstrawberry Avez-vous essayé la solution? La solution a dessiné le segment de ligne en pointillé par segment. C'est juste un POC et inutile en pratique!
Yu Jianrong
6

Il existe un outil sympa créé par @kovart appelé le générateur de bordure en pointillés .

Il utilise un svg comme image d'arrière-plan pour permettre de définir le tableau de tirets de trait souhaité, et est assez pratique.

Vous l'utiliseriez alors simplement comme propriété d'arrière-plan sur votre élément à la place de la bordure:

div {
  background-image: url("data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' fill='none' stroke='black' stroke-width='4' stroke-dasharray='6%2c 14' stroke-dashoffset='0' stroke-linecap='square'/%3e%3c/svg%3e");
  padding: 20px;
  display: inline-block;
}
Balthazar
la source
C'est une solution simple, facile et rapide
jamesioppolo
Cela a bien fonctionné!
Kevin Raffay le
3

La longueur du trait dépend de la largeur du trait. Vous pouvez augmenter la longueur en augmentant la largeur et masquer une partie de la bordure par élément interne.

.thin {
    background: #F4FFF3;
    border: 2px dashed #3FA535;  
    position: relative;
}

.thin:after {
    content: '';
    position: absolute;
    left: -1px;
    top: -1px;
    right: -1px;
    bottom: -1px;
    border: 1px solid #F4FFF3;
}

https://jsfiddle.net/ok6srt2z/

ili4
la source
Mais de cette façon, vous ne pourrez pas cliquer sur le contenu de l'élément d'origine car le pseudo-élément "après" le couvrira. Le meilleur moyen est donc d'utiliser SVG.
ili4 le
Vous pouvez ajouter pointer-events: nonepour éviter le problème de superposition.
benJ
0

J'ai récemment eu le même problème.

J'ai réussi à le résoudre avec deux divs positionnés de manière absolue portant la bordure (un pour l'horizontale et l'autre pour le vertical), puis en les transformant. La boîte extérieure a juste besoin d'être positionnée de manière relative.

<div class="relative">
    <div class="absolute absolute--fill overflow-hidden">
        <div class="absolute absolute--fill b--dashed b--red"
            style="
                border-width: 4px 0px 4px 0px;
                transform: scaleX(2);
        "></div>
        <div class="absolute absolute--fill b--dashed b--red"
            style="
                border-width: 0px 4px 0px 4px;
                transform: scaleY(2);
        "></div>
    </div>

    <div> {{Box content goes here}} </div>
</div>

Remarque: j'ai utilisé des tachyons dans cet exemple, mais je suppose que les classes sont assez explicites.

razzz
la source
-1

Cela créera une bordure orange et grise en utilisant le class = "myclass" sur le div.

.myclass {
    outline:dashed darkorange  12px;
    border:solid slategray  14px;
    outline-offset:-14px;
}
BJC
la source
Par "offrir un meilleur contrôle de l'apparence des bordures en pointillés", l'OP (Affiche originale) signifie qu'il souhaite contrôler la longueur de chaque tiret, comme indiqué au début de la question. Désolé pour toute confusion.
Skylar