Controle la longitud del trazo del borde punteado y la distancia entre trazos

124

¿Es posible controlar la longitud y la distancia entre los trazos de borde punteado en CSS?

Este ejemplo a continuación se muestra de manera diferente entre los navegadores:

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

Grandes diferencias: IE 11 / Firefox / Chrome

Borde IE 11Borde de FirefoxBorde cromado

¿Existe algún método que pueda proporcionar un mayor control de la apariencia de los bordes discontinuos?

AntonAL
fuente

Respuestas:

157

El valor de la propiedad del borde de guiones nativos no ofrece control sobre los guiones en sí mismos ... ¡así que traiga la border-imagepropiedad!

Elabora tu propia frontera con border-image

Compatibilidad : ofrece un excelente soporte para navegadores (IE 11 y todos los navegadores modernos). Se puede configurar un borde normal como respaldo para navegadores más antiguos.

Vamos a crear estos

¡Estos bordes mostrarán exactamente el mismo navegador cruzado!

Ejemplo de objetivo Ejemplo de objetivo con brechas más amplias

Paso 1: crea una imagen adecuada

Este ejemplo tiene 15 píxeles de ancho por 15 píxeles de alto y los espacios son actualmente de 5 píxeles de ancho. Es un .png con transparencia.

Así es como se ve en Photoshop cuando se amplía:

Ejemplo de fondo de imagen de borde agrandado

Así es como se ve a escala:

Ejemplo de borde de imagen de fondo Tamaño real

Controlar el espacio y la longitud de la carrera

Para crear espacios o trazos más amplios / más cortos, amplíe / acorte los espacios o trazos en la imagen.

Aquí hay una imagen con espacios más amplios de 10 píxeles:

Huecos más grandes correctamente escalado = Grandes lagunas para escalar

Paso 2: crea el CSS: este ejemplo requiere 4 pasos básicos

  1. Defina la fuente de la imagen del borde :

    border-image-source:url("http://i.stack.imgur.com/wLdVc.png");  
  2. Opcional : defina el ancho de la imagen del borde :

    border-image-width: 1;

    El valor predeterminado es 1. También se puede configurar con un valor de píxel, un valor de porcentaje o como otro múltiplo (1x, 2x, 3x, etc.). Esto anula cualquier border-widthconjunto.

  3. Defina el segmento de imagen de borde :

    En este ejemplo, el grosor de los bordes superior, derecho, inferior e izquierdo de las imágenes es de 2px, y no hay espacios fuera de ellos, por lo que nuestro valor de corte es 2:

    border-image-slice: 2; 

    Los cortes se ven así, 2 píxeles de la parte superior, derecha, inferior e izquierda:

    Ejemplo de rebanadas

  4. Defina el borde-imagen-repetición :

    En este ejemplo, queremos que el patrón se repita uniformemente alrededor de nuestro div. Entonces elegimos:

    border-image-repeat: round;

Escribir taquigrafía

Las propiedades anteriores se pueden establecer individualmente o de forma abreviada usando border-image :

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

Ejemplo completo

Tenga en cuenta el border: dashed 4px #000retroceso. Los navegadores no compatibles recibirán este borde.

.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>

misterManSam
fuente
Tenga en cuenta que debe especificar border-style: solid(o algo similar) si omite el respaldo.
Robbendebiene
Esta solución no funciona con el atributo 'border-color'
Michael Rovinsky
102

Además de la border-imagepropiedad, hay algunas otras formas de crear un borde punteado con control sobre la longitud del trazo y la distancia entre ellos. Se describen a continuación:

Método 1: usar SVG

Podemos crear el borde punteado usando pathun polygonelemento o un y estableciendo elstroke-dasharray propiedad. La propiedad toma dos parámetros donde uno define el tamaño del guión y el otro determina el espacio entre ellos.

Pros:

  1. Los SVG por naturaleza son gráficos escalables y pueden adaptarse a cualquier dimensión de contenedor.
  2. Puede funcionar muy bien incluso si hay un border-radiusinvolucrado. Simplemente deberíamos reemplazar el pathcon un me circlegusta en esta respuesta (o) convertir el pathen un círculo.
  3. El soporte del navegador para SVG es bastante bueno y se puede proporcionar respaldo usando VML para IE8-.

Contras:

  1. Cuando las dimensiones del contenedor no cambian proporcionalmente, las rutas tienden a escalar, lo que resulta en un cambio en el tamaño del guión y el espacio entre ellos (intente colocar el cursor sobre el primer cuadro del fragmento). Esto se puede controlar agregando vector-effect='non-scaling-stroke'(como en el segundo cuadro) pero el soporte del navegador para esta propiedad es nulo en IE.


Método 2: usar degradados

Podemos utilizar varias linear-gradientimágenes de fondo y colocarlas de forma adecuada para crear un efecto de borde discontinuo. Esto también se puede hacer con a, repeating-linear-gradientpero no hay mucha mejora debido al uso de un gradiente repetido, ya que necesitamos que cada gradiente se repita en una sola dirección.

Pros:

  1. Escalable y adaptable incluso si las dimensiones del contenedor son dinámicas.
  2. No hace uso de ningún pseudoelemento adicional, lo que significa que se pueden mantener a un lado para cualquier otro uso potencial.

Contras:

  1. El soporte del navegador para gradientes lineales es comparativamente menor y esto no es posible si desea admitir IE 9-. Incluso bibliotecas como CSS3 PIE no admiten la creación de patrones de degradado en IE8-.
  2. No se puede usar cuando border-radiusestá involucrado porque los fondos no se curvan en función de border-radius. En su lugar, se recortan.

Método 3: Sombras de caja

Podemos crear una pequeña barra (en la forma del guión) usando pseudoelementos y luego crear múltiples box-shadowversiones para crear un borde como en el fragmento de abajo.

Si el guión tiene forma cuadrada, un solo pseudo-elemento sería suficiente, pero si es un rectángulo, necesitaríamos un pseudo-elemento para los bordes superior + inferior y otro para los bordes izquierdo + derecho. Esto se debe a que la altura y el ancho del guión en el borde superior serán diferentes a los de la izquierda.

Pros:

  1. Las dimensiones del guión se pueden controlar cambiando las dimensiones del pseudoelemento. El espaciado se puede controlar modificando el espacio entre cada sombra.
  2. Se puede producir un efecto único agregando un color diferente para cada sombra de caja.

Contras:

  1. Dado que tenemos que establecer manualmente las dimensiones del guión y el espaciado, este enfoque no es bueno cuando las dimensiones del cuadro principal son dinámicas.
  2. IE8 y versiones inferiores no admiten la sombra de cuadro . Sin embargo, esto se puede solucionar utilizando bibliotecas como CSS3 PIE.
  3. Se puede usar con, border-radiuspero colocarlos sería muy complicado al tener que encontrar puntos en un círculo (y posiblemente incluso transform).

Harry
fuente
Si va a utilizar la solución svg, le aconsejo que la agregue pointer-events:nonea svg para poder interactuar con el contenido.
Sodj
Maravillosa respuesta.
Desviación
22

Uno corto: No, no lo es. En su lugar, tendrá que trabajar con imágenes.

Jamón Vocke
fuente
5
esta respuesta está desactualizada a partir de 2018
godblessstrawberry
2
@WilliamHampshire Me gustaría ir con esta técnica youtu.be/vs34f9FiHps?t=779 pero comprueba respuesta aceptada, que le gustaría otras soluciones más
godblessstrawberry
1
@godblessstrawberry ¡¡Gracias !! Pero eso es usar SVG, así que todavía no usa solo css ...
Kyle Krzeski
1
@WilliamHampshire hay una solución de sombra de caja en el hilo Quise decir la respuesta de Harry
godblessstrawberry
@godblessstrawberry ¿Has probado la solución? La solución dibujó la línea punteada segmento por segmento. ¡Es solo un POC e inútil en la práctica!
Yu Jianrong
6

Hay una herramienta genial creada por @kovart llamada generador de bordes discontinuos .

Utiliza un svg como imagen de fondo para permitir configurar la matriz de trazos y trazos que desee, y es bastante conveniente.

Luego, simplemente lo usaría como la propiedad de fondo en su elemento en lugar del borde:

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;
}
Baltasar
fuente
Esta es una solución simple, fácil y rápida
jamesioppolo
¡Esto funcionó bien!
Kevin Raffay
3

La longitud del trazo depende del ancho del trazo. Puede aumentar la longitud aumentando el ancho y ocultar parte del borde por elemento interno.

.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
fuente
Pero de esta manera no podrá hacer clic en el contenido del elemento original porque el pseudoelemento "después" lo cubrirá. Entonces, la mejor manera es usar SVG.
ili4
Puede agregar pointer-events: nonepara evitar el problema de superposición.
BenJ
0

Recientemente tuve el mismo problema.

Logré resolverlo con dos divs absolutamente posicionados llevando el borde (uno para horizontal y otro para vertical), y luego transformándolos. La caja exterior solo necesita estar relativamente posicionada.

<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>

Nota: utilicé taquiones en este ejemplo, pero supongo que las clases se explican por sí mismas.

razzz
fuente
-1

Esto creará un borde naranja y gris usando class = "myclass" en el div.

.myclass {
    outline:dashed darkorange  12px;
    border:solid slategray  14px;
    outline-offset:-14px;
}
BJC
fuente
Al "proporcionar un mayor control de la apariencia de los bordes punteados", el OP (Póster original) significa que quiere controlar la longitud de cada guión, como se indica al principio de la pregunta. Perdón por cualquier confusión.
Skylar