Rayon de contour?

473

Est-il possible d'obtenir des coins arrondis sur le contour d'un div element, similaire à border-radius?

Marc Guerin
la source
2
Eh bien, j'ai une boîte Div avec une bordure grise 2px avec un rayon de bordure 20px, je me promenais si je pouvais avoir un Outine 10px autour de cette frontière qui suit la frontière plutôt que d'être carré
Marc Guerin
4
C'est une bonne question. Un élément avec border: 5px redet outline: 5px blueet border-radius: 5px, la bordure est arrondie, mais le contour est carré.
Matthew Rudy
4
Jusqu'à présent, nous ne pouvons l'utiliser que dans Firefox:-moz-outline-radius
Wojciech Bednarski
Cela devrait faire partie de CSS3 ... Si j'y pense - je déteste le W3C: D
m93a
17
vous en avez tous besoin box-shadowdans votre vie ..
Muhammad Umer

Réponses:

539

Ancienne question maintenant, mais cela pourrait être pertinent pour quelqu'un avec un problème similaire. J'avais un champ de saisie arrondi borderet je voulais changer la couleur du contour de mise au point. Je ne pouvais pas apprivoiser l'horrible carré outlineau contrôle d'entrée.

Au lieu de cela, j'ai utilisé box-shadow. En fait, j'ai préféré l'aspect lisse de l'ombre, mais l'ombre peut être durcie pour simuler un contour arrondi:

 /* Smooth outline with box-shadow: */
    .text1:focus {
        box-shadow: 0 0 3pt 2pt red;
    }

    /* Hard "outline" with box-shadow: */
    .text2:focus {
        box-shadow: 0 0 0 2pt red;
    }
<input type=text class="text1"> 
<br>
<br>
<br>
<br>
<input type=text class="text2">

Lea Hayes
la source
24
OMI, c'est la réponse que vous cherchez. J'ai fait cette méthode, mais n'oubliez pas de transformer votre plan à 0.
John Morton
2
C'est exactement ce que je cherchais, et s'adapte encore mieux qu'un rayon de contour.
Zenexer
2
L'exemple de plan dur ne fonctionne pas. C'est juste un rectangle sans rayon d'angle.
Erik Aigner
1
outline: 0rompt l'accessibilité du Web; lire outlinenone.com
ianstarz
4
@ianstarz, il rompt l'accessibilité lorsque vous ne fournissez aucun style alternatif. box-shadowest le style alternatif (qui, comme présenté ici, est en fait très similaire en apparence outline).
ACJ
85

J'accomplis généralement ceci en utilisant le pseudo-élément: after:

bien sûr, cela dépend de l'utilisation, cette méthode permet de contrôler les frontières individuelles, plutôt que d'utiliser la méthode de l'ombre dure.

vous pouvez également définir des décalages de -1px et utiliser à nouveau un dégradé linéaire d'arrière-plan (pas de bordure) pour un effet différent.

body {
  margin: 20px;
}

a {
  background: #999;
  padding: 10px 20px;
  border-radius: 5px;
  text-decoration: none;
  color: #fff;
  position: relative;
  border: 2px solid #000;
}

a:after {
  content: '';
  display: block;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  border-radius: 5px;
  border: 2px solid #ccc;
}
<a href="#">Button</a>

mononyme
la source
4
Une version modifiée et un peu plus spectaculaire: jsfiddle.net/rh6j3cdm .
Dávid Horváth
2
Il n'est pas possible de faire un pseudo :: after pour un champ de saisie
Simon Franzen
merci, cela a très bien fonctionné avec les contours de la requête de recherche de react-sortable-tree!
Monarch Wadia
J'aime cette solution car elle est beaucoup plus flexible que la box-shadowversion. Par exemple, si vous voulez que le "contour" soit éloigné de l'élément (c'est-à-dire la simulation outline-offset), cela devient possible avec cette technique.
Kirk Woll du
34

Similaire à Lea Hayes ci-dessus, mais voici comment je l'ai fait:

div {
  background: #999;
  height: 100px;
  width: 200px;
  border: #999 solid 1px;
  border-radius: 10px;
  margin: 15px;
  box-shadow: 0px 0px 0px 1px #fff inset;
}
<div></div>

Aucune imbrication de DIV ou jQuery nécessaire, Altho pour des raisons de brièveté, j'ai omis les variantes -moz et -webkit de certains CSS. Vous pouvez voir le résultat ci-dessus

Heraldmonkey
la source
6
Il parle du contour, pas de la frontière ... rayon "contour"
android.nick
5
correct, mais comme le contour-rayon n'est pas disponible, ma méthode donne l'apparence d'une bordure ainsi que d'un contour. Il s'agit d'un effet visuel, donc à moins que la conception de Marc ne soit spécifiée jusqu'au pixel près, le fait qu'il n'utilise pas réellement la propriété de contour ne fait aucune différence. Et puisque c'est une solution pratique, j'apprécierais le vote de retour
Heraldmonkey
2
Cela a très bien fonctionné. Je n'ai pas utilisé inset, cependant, et j'ai obtenu ce que je voulais.
Paul Schreiber
18

Je voulais une bonne accessibilité au focus pour les menus déroulants dans une barre de navigation Bootstrap, et j'étais assez satisfait de ceci:

     a.dropdown-toggle:focus {
         display: inline-block;
         box-shadow: 0 0 0 2px #88b8ff;
         border-radius: 2px;
     }
<a href="https://stackoverflow.com" class="dropdown-toggle">Visit Stackoverflow</a>

StackOverflowUser
la source
16

Vous cherchez quelque chose comme ça , je pense.

div {
    -webkit-border-radius: 10px;
    -moz-border-radius: 10px;
    border-radius: 10px;
    border: 1px solid black;
    background-color: #CCC;
    height: 100px;
    width: 160px;
}

Éditer

Il n'y a que Firefox uniquement -moz-outline-radius, mais cela ne fonctionnera pas sur IE / Chrome / Safari / Opera / etc. Ainsi, il semble que la façon la plus compatible avec tous les navigateurs * pour obtenir une ligne courbe autour d'une bordure consiste à utiliser un div wrapper:

div.inner {
  -webkit-border-radius: 10px;
  -moz-border-radius: 10px;
  border-radius: 10px;
  border: 1px solid black;
  background-color: #CCC;
  height: 100px;
  width: 160px;
}

div.outer {
  display: inline-block;
  -webkit-border-radius: 10px;
  -moz-border-radius: 10px;
  border-radius: 10px;
  border: 1px solid red;
}
<div class="outer">
  <div class="inner"></div>
</div>


* en dehors de l'utilisation d'images

Matt Ball
la source
20
Non, je sais comment obtenir le Border Radius que j'errais si vous pouviez obtenir un Outline-Radius
Marc Guerin
Tu veux dire quoi exactement? Un contour plus épais, comme ça? jsfiddle.net/mattball/NXZFv/1
Matt Ball
10
@Matt: un contour incurvé au lieu d'une bordure , évidemment. Voir w3.org/TR/CSS21/ui.html#dynamic-outlines
Joey
Eh bien, j'ai une boîte Div avec une bordure grise 2px avec un rayon de bordure 20px, je me demandais si je pouvais avoir une sortie 10px autour de cette bordure qui suit la bordure plutôt que d'être carrée.
Marc Guerin
1
Juste un ajout à votre code mat, si vous laissez tomber le rayon de la bordure de quelques px sur la boîte intérieure, le coin devient alors beaucoup plus serré, merci pour votre aide
Marc Guerin
7

Je viens de trouver une excellente solution pour cela, et après avoir examiné toutes les réponses jusqu'à présent, je ne l'ai pas encore vue publiée. Alors, voici ce que j'ai fait:

J'ai créé une règle CSS pour la classe et utilisé une pseudo-classe de: focus pour cette règle. J'ai décidé outline: nonede me débarrasser de ce `` contour '' bleu clair sans rayon de bordure que Chrome utilise par défaut. Ensuite, dans cette même :focuspseudo-classe, où ce contour n'existe plus, j'ai ajouté mes propriétés de rayon et de bordure. Menant à ce qui suit

outline: none;
border-radius: 5px;
border: 2px solid maroon;

pour avoir un contour de couleur marron avec un rayon de bordure qui apparaît maintenant lorsque l'élément est sélectionné par l'utilisateur par tabulation.

Branden Pinney
la source
L'utilisation de "contour: 0" ou "contour: aucun" est considérée comme une mauvaise pratique et gâche l'accessibilité des utilisateurs. À ce stade, je n'ai pas de correctif, mais voici un article expliquant pourquoi vous ne devriez pas supprimer le contour si possible et quoi faire si vous devez absolument le faire. Ne supprimez jamais les contours CSS
AndrewBrntt
5

Si vous voulez obtenir un aspect en relief, vous pouvez faire quelque chose comme ceci:

.embossed {
  background: #e5e5e5;
  height: 100px;
  width: 200px;
  border: #FFFFFF solid 1px;
  outline: #d0d0d0 solid 1px;
  margin: 15px;
}

.border-radius {
  border-radius: 20px 20px 20px 20px;
  -webkit-border-radius: 20px;
  -moz-border-radius: 20px;
  -khtml-border-radius: 20px;
}

.outline-radius {
  -moz-outline-radius: 21px;
}
<div class="embossed"></div>
<div class="embossed border-radius"></div>
<div class="embossed border-radius outline-radius">-MOZ ONLY</div>

Je n'ai trouvé aucun moyen de contourner ce problème dans d'autres navigateurs.

EDIT: La seule autre façon de le faire est d'utiliser l'ombre de boîte, mais cela ne fonctionnera pas si vous avez déjà une ombre de boîte sur cet élément.

James Kyle
la source
1
Vous pouvez utiliser plusieurs ombres sur le même élément, en les séparant par des virgules.
Bangash
2

Il y a la solution si vous avez seulement besoin de contour sans bordure. Ce n'est pas le mien. J'ai obtenu si du fichier css Bootstrap. Si vous spécifiez outline: 1px auto certain_color, vous obtiendrez une fine ligne extérieure autour de div d'une certaine couleur. Dans ce cas, la largeur spécifiée n'a pas d'importance, même si vous spécifiez une largeur de 10 px, ce sera de toute façon une ligne mince. Le mot clé dans la règle mentionnée est "auto".
Si vous avez besoin d'un contour avec des coins arrondis et une certaine largeur, vous pouvez ajouter une règle CSS sur la bordure avec la largeur nécessaire et la même couleur. Il rend le contour plus épais.

Aleks Sid
la source
2

Pour autant que je sache, le Outline radiusn'est pris en charge que par Firefox et Firefox pour Android.

-moz-outline-radius: 1em;

entrez la description de l'image ici

ucMedia
la source
1

Non. Les bordures se trouvent à l'extérieur de l'élément et à l'intérieur de la zone de marge du modèle boîte. Les contours se trouvent à l'intérieur de l'élément et la zone de remplissage du modèle de boîte l'ignore. Il n'est pas destiné à l'esthétique. C'est juste pour montrer au designer les contours des éléments. Par exemple, au début du développement d'un document html, un développeur peut avoir besoin de discerner rapidement s'il a placé toutes les divisions squelettiques au bon endroit. Plus tard, ils devront peut-être vérifier si les différents boutons et formulaires sont à la bonne distance les uns des autres.

Les frontières sont de nature esthétique. Contrairement aux contours, ils sont en fait séparés du modèle de boîte, ce qui signifie qu'ils ne chevauchent pas le texte défini sur margin: 0; et chaque côté de la bordure peut être stylisé individuellement.

Si vous essayez d'appliquer un rayon d'angle au contour, je suppose que vous l'utilisez comme la plupart des gens utilisent la bordure. Donc, si cela ne vous dérange pas de me demander, quelle propriété de contour le rend souhaitable au-delà de la frontière?

Musixauce3000
la source
10
Les contours ont pour but la navigation / l'accessibilité au clavier, et non pour montrer aux développeurs où se trouvent les éléments
danwellman
Eh bien, c'est pour cela que les navigateurs les utilisent, par défaut. Mais je les ai toujours utilisés pour voir où sont mes divs, avec grand effet.
Musixauce3000
+1 pour avoir mentionné que "les bordures se trouvent à l'extérieur de l'élément et à l'intérieur de la zone de marge du modèle de boîte. Les contours se trouvent à l'intérieur de l'élément et la zone de remplissage du modèle de boîte l'ignore."
Jacques
1

COMBINAISON DE L'OMBRE ET DU PLAN DE LA BOÎTE.

Une légère torsion sur la réponse de Lea Hayes que j'ai trouvée

input[type=text]:focus {
    box-shadow: 0 0 0 1pt red;
    outline-width: 1px;
    outline-color: red;
}

obtient une très belle finition propre. Pas de saut de taille que vous obtenez lorsque vous utilisez border-radius

fidev
la source
1

Comme d'autres l'ont dit, seul Firefox prend en charge cela. Voici un travail qui fait la même chose et fonctionne même avec des contours en pointillés.

exemple

.has-outline {
    display: inline-block;
    background: #51ab9f;
    border-radius: 10px;
    padding: 5px;
    position: relative;
}
.has-outline:after {
  border-radius: 10px;
  padding: 5px;
  border: 2px dashed #9dd5cf;
  position: absolute;
  content: '';
  top: -2px;
  left: -2px;
  bottom: -2px;
  right: -2px;
}
<div class="has-outline">
  I can haz outline
</div>

RobKohr
la source
0

Essayez d'utiliser un remplissage et une couleur d'arrière-plan pour la bordure, puis une bordure pour le contour:

.round_outline {
  padding: 8px;
  background-color: white;
  border-radius: 50%;
  border: 1px solid black;
}

A travaillé dans mon cas.

Eric
la source
0

Je mets juste le contour transparent.

input[type=text] {
  outline: rgba(0, 0, 0, 0);
  border-radius: 10px;
}

input[type=text]:focus {    
  border-color: #0079ff;
}
Ireneml.fr
la source
0

J'aime cette façon.

.circle:before {
   content: "";
   width: 14px;
   height: 14px;
   border: 3px solid #fff;
   background-color: #ced4da;
   border-radius: 7px;
   display: inline-block;
   margin-bottom: -2px;
   margin-right: 7px;
   box-shadow: 0px 0px 0px 1px #ced4da;
}

Il créera un cercle gris avec une bordure autour d'elle et encore 1px autour de la bordure!

Andris
la source
0
clip-path: circle(100px at center);

Cela rendra le cercle cliquable uniquement, tandis que border-radius fait toujours un carré, mais ressemble à un cercle.

Martin Zvarík
la source
0

La réponse simple à la question de base est non. La seule option multi-navigateur consiste à créer un hack qui accomplit ce que vous voulez. Cette approche comporte certains problèmes potentiels en ce qui concerne le style du contenu préexistant , mais elle offre plus de personnalisation du contour (décalage, largeur, style de ligne) que la plupart des autres solutions.

À un niveau de base, considérez l'exemple statique suivant (exécutez le snippent pour la démonstration):

.outline {
    border: 2px dotted transparent;
    border-radius: 5px;
    display: inline-block;
    padding: 2px;
    margin: -4px;
}

/* :focus-within does not work in Edge or IE */
.outline:focus-within, .outline.edge {
    border-color: blue;
}

br {
    margin-bottom: 0.75rem;
}
<h3>Javascript-Free Demo</h3>
<div class="outline edge"><input type="text" placeholder="I always have an outline"/></div><br><div class="outline"><input type="text" placeholder="I have an outline when focused"/></div> *<i>Doesn't work in Edge or IE</i><br><input type="text" placeholder="I have never have an outline" />
<p>Note that the outline does not increase the spacing between the outlined input and other elements around it. The margin (-4px) compensates for the space that the outlines padding (-2px) and width (2px) take up, a total of 4px.</p>

Maintenant, à un niveau plus avancé, il serait possible d'utiliser JavaScript pour amorcer des éléments d'un type ou d'une classe donné afin qu'ils soient encapsulés dans un div qui simule un plan lors du chargement de la page. De plus, des liaisons d'événement peuvent être établies pour afficher ou masquer le contour des interactions utilisateur comme ceci (exécutez l'extrait ci-dessous ou ouvrez-le dans JSFiddle ):

h3 {
  margin: 0;
}

div {
  box-sizing: border-box;
}

.flex {
  display: flex;
}

.clickable {
  cursor: pointer;
}

.box {
  background: red;
  border: 1px solid black;
  border-radius: 10px;
  height: 5rem;
  display: flex;
  align-items: center;
  text-align: center;
  color: white;
  font-weight: bold;
  padding: 0.5rem;
  margin: 1rem;
}
<h3>Javascript-Enabled Demo</h3>
<div class="flex">
  <div class="box outline-me">I'm outlined because I contain<br>the "outline-me" class</div>
  <div class="box clickable">Click me to toggle outline</div>
</div>
<hr>
<input type="text" placeholder="I'm outlined when focused" />

<script>
// Called on an element to wrap with an outline and passed a styleObject
// the styleObject can contain the following outline properties:
// 		style, width, color, offset, radius, bottomLeftRadius,
//		bottomRightRadius, topLeftRadius, topRightRadius
// It then creates a new div with the properties specified and 
// moves the calling element into the div
// The newly created wrapper div receives the class "simulated-outline"
Element.prototype.addOutline = function (styleObject, hideOutline = true) {
    var element = this;

    // create a div for simulating an outline
    var outline = document.createElement('div');

    // initialize css formatting
    var css = 'display:inline-block;';

    // transfer any element margin to the outline div
    var margins = ['marginTop', 'marginBottom', 'marginLeft', 'marginRight'];
    var marginPropertyNames = { 
        marginTop: 'margin-top',
        marginBottom: 'margin-bottom',
        marginLeft: 'margin-left',
        marginRight: 'margin-right'
    }
    var outlineWidth = Number.parseInt(styleObject.width);
    var outlineOffset = Number.parseInt(styleObject.offset);
    for (var i = 0; i < margins.length; ++i) {
        var computedMargin = Number.parseInt(getComputedStyle(element)[margins[i]]);
        var margin = computedMargin - outlineWidth - outlineOffset;
        css += marginPropertyNames[margins[i]] + ":" + margin + "px;";
    }
    element.style.cssText += 'margin:0px !important;';
    
    // compute css border style for the outline div
    var keys = Object.keys(styleObject);
    for (var i = 0; i < keys.length; ++i) {
        var key = keys[i];
        var value = styleObject[key];
        switch (key) {
            case 'style':
                var property = 'border-style';
                break;
            case 'width':
                var property = 'border-width';
                break;
            case 'color':
                var property = 'border-color';
                break;
            case 'offset':
                var property = 'padding';
                break;
            case 'radius':
                var property = 'border-radius';
                break;
            case 'bottomLeftRadius':
                var property = 'border-bottom-left-radius';
                break;
            case 'bottomRightRadius':
                var property = 'border-bottom-right-radius';
                break;
            case 'topLeftRadius':
                var property = 'border-top-left-radius-style';
                break;
            case 'topRightRadius':
                var property = 'border-top-right-radius';
                break;
        }
        css += property + ":" + value + ';';
    }
    
    // apply the computed css to the outline div
    outline.style.cssText = css;
    
    // add a class in case we want to do something with elements
    // receiving a simulated outline
    outline.classList.add('simulated-outline');
    
    // place the element inside the outline div
    var parent = element.parentElement;
    parent.insertBefore(outline, element);
    outline.appendChild(element);

    // determine whether outline should be hidden by default or not
    if (hideOutline) element.hideOutline();
}

Element.prototype.showOutline = function () {
    var element = this;
    // get a reference to the outline element that wraps this element
    var outline = element.getOutline();
    // show the outline if one exists
    if (outline) outline.classList.remove('hide-outline');
}


Element.prototype.hideOutline = function () {
    var element = this;
    // get a reference to the outline element that wraps this element
    var outline = element.getOutline();
    // hide the outline if one exists
    if (outline) outline.classList.add('hide-outline');
}

// Determines if this element has an outline. If it does, it returns the outline
// element. If it doesn't have one, return null.
Element.prototype.getOutline = function() {
    var element = this;
    var parent = element.parentElement;
    return (parent.classList.contains('simulated-outline')) ? parent : null;
}

// Determines the visiblity status of the outline, returning true if the outline is
// visible and false if it is not. If the element has no outline, null is returned.
Element.prototype.outlineStatus = function() {
    var element = this;
    var outline = element.getOutline();
    if (outline === null) {
        return null;
    } else {
        return !outline.classList.contains('hide-outline');
    }
}

// this embeds a style element in the document head for handling outline visibility
var embeddedStyle = document.querySelector('#outline-styles');
if (!embeddedStyle) {
    var style = document.createElement('style');
    style.innerText = `
        .simulated-outline.hide-outline {
            border-color: transparent !important;
        }
    `;
    document.head.append(style);
}


/*########################## example usage ##########################*/

// add outline to all elements with "outline-me" class
var outlineMeStyle = {
    style: 'dashed',
    width: '3px',
    color: 'blue',
    offset: '2px',
    radius: '5px'
};
document.querySelectorAll('.outline-me').forEach((element)=>{
  element.addOutline(outlineMeStyle, false);
});


// make clickable divs get outlines
var outlineStyle = {
    style: 'double',
    width: '4px',
    offset: '3px',
    color: 'red',
    radius: '10px'
};
document.querySelectorAll('.clickable').forEach((element)=>{
    element.addOutline(outlineStyle);
    element.addEventListener('click', (evt)=>{
        var element = evt.target;
        (element.outlineStatus()) ? element.hideOutline() : element.showOutline();
    });
});


// configure inputs to only have outline on focus
document.querySelectorAll('input').forEach((input)=>{
    var outlineStyle = {
        width: '2px',
        offset: '2px',
        color: 'black',
        style: 'dotted',
        radius: '10px'
    }
    input.addOutline(outlineStyle);
    input.addEventListener('focus', (evt)=>{
        var input = evt.target;
        input.showOutline();
    });
    input.addEventListener('blur', (evt)=>{
        var input = evt.target;
        input.hideOutline();
    });
});
</script>

En terminant, permettez-moi de répéter, que la mise en œuvre de cette approche peut nécessiter plus de style que ce que j'ai inclus dans mes démos, surtout si vous avez déjà stylisé l'élément que vous souhaitez décrire.

b_laoshi
la source