Controlar o comprimento do traçado da borda tracejada e a distância entre os traços

124

É possível controlar o comprimento e a distância entre os traços de borda tracejada no CSS?

Este exemplo abaixo é exibido de maneira diferente entre os navegadores:

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

Grandes diferenças: IE 11 / Firefox / Chrome

Fronteira IE 11Fronteira do FirefoxBorda cromada

Existem métodos que podem fornecer maior controle da aparência das bordas tracejadas?

AntonAL
fonte

Respostas:

157

O valor da propriedade da borda tracejada nativa não oferece controle sobre os traços propriamente ditos ... portanto, traga a border-imagepropriedade!

Faça sua própria fronteira com border-image

Compatibilidade : Oferece excelente suporte ao navegador (IE 11 e todos os navegadores modernos). Uma borda normal pode ser definida como um substituto para navegadores mais antigos.

Vamos criar estes

Essas bordas exibirão exatamente o mesmo navegador cruzado!

Exemplo de meta Exemplo de objetivo com intervalos maiores

Etapa 1 - Crie uma imagem adequada

Este exemplo tem 15 pixels de largura por 15 pixels de altura e as lacunas atualmente têm 5 px de largura. É um .png com transparência.

Isto é o que parece no photoshop quando ampliado:

Exemplo de fundo da imagem da borda ampliado

É assim que parece escalar:

Exemplo de tamanho real do plano de fundo da imagem da borda

Controle de folga e comprimento do curso

Para criar intervalos ou traços mais largos / curtos, amplie / reduza os intervalos ou traços na imagem.

Aqui está uma imagem com intervalos maiores de 10 px:

Lacunas maiores corretamente dimensionado = Lacunas maiores em escala

Etapa 2 - Crie o CSS - este exemplo requer 4 etapas básicas

  1. Defina a origem da imagem da borda :

    border-image-source:url("http://i.stack.imgur.com/wLdVc.png");  
  2. Opcional - Defina a largura da imagem da borda :

    border-image-width: 1;

    O valor padrão é 1. Ele também pode ser definido com um valor de pixel, valor percentual ou como outro múltiplo (1x, 2x, 3x etc). Isso substitui qualquer border-widthconjunto.

  3. Defina a fatia da imagem da borda :

    Neste exemplo, a espessura das bordas superior, direita, inferior e esquerda das imagens é de 2px e não há espaço fora delas, portanto, o valor da fatia é 2:

    border-image-slice: 2; 

    As fatias ficam assim, a 2 pixels da parte superior, direita, inferior e esquerda:

    Exemplo de fatias

  4. Defina a repetição da imagem da borda :

    Neste exemplo, queremos que o padrão se repita uniformemente em torno de nossa div. Então escolhemos:

    border-image-repeat: round;

Escrevendo taquigrafia

As propriedades acima podem ser definidas individualmente ou em forma abreviada usando border-image :

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

Exemplo completo

Observe o border: dashed 4px #000fallback. Navegadores não compatíveis receberão essa borda.

.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
fonte
Observe que você precisa especificar border-style: solid(ou algo semelhante) se você omitir o fallback.
Robbendebiene
Esta solução não funciona com o atributo 'border-color'
Michael Rovinsky
100

Em adição ao border-image propriedade, existem algumas outras maneiras de criar uma borda tracejada com controle sobre o comprimento do traçado e a distância entre eles. Eles são descritos abaixo:

Método 1: usando SVG

Podemos criar a borda tracejada usando um pathou um polygonelemento e definindo a stroke-dasharraypropriedade A propriedade usa dois parâmetros em que um define o tamanho do traço e o outro determina o espaço entre eles.

Prós:

  1. Os SVGs por natureza são gráficos escalonáveis ​​e podem se adaptar a qualquer dimensão de contêiner.
  2. Pode funcionar muito bem, mesmo se houver um border-radiusenvolvido. Teríamos apenas substituído o pathcom um circleigual nesta resposta (ou) convertido o pathem um círculo.
  3. O suporte ao navegador para SVG é muito bom e o fallback pode ser fornecido usando o VML for IE8-.

Contras:

  1. Quando as dimensões do contêiner não mudam proporcionalmente, os caminhos tendem a ser redimensionados, resultando em uma alteração no tamanho do traço e no espaço entre eles (tente passar o mouse na primeira caixa do snippet). Isso pode ser controlado adicionando vector-effect='non-scaling-stroke'(como na segunda caixa), mas o suporte ao navegador para essa propriedade é nulo no IE.


Método 2: usando gradientes

Podemos usar várias linear-gradientimagens de fundo e posicioná-las adequadamente para criar um efeito de borda tracejada. Isso também pode ser feito com a, repeating-linear-gradientmas não há muita melhoria devido ao uso de um gradiente de repetição, pois precisamos que cada gradiente seja repetido em apenas uma direção.

Prós:

  1. Escalável e pode se adaptar mesmo que as dimensões do contêiner sejam dinâmicas.
  2. Não utiliza pseudoelementos extras, o que significa que eles podem ser mantidos de lado para qualquer outro uso potencial.

Contras:

  1. O suporte do navegador para gradientes lineares é comparativamente mais baixo e isso é desnecessário se você deseja oferecer suporte ao IE 9-. Mesmo bibliotecas como CSS3 PIE não suportam a criação de padrões de gradiente no IE8-.
  2. Não pode ser usado quando border-radiusestá envolvido porque os fundos não se curvam com base border-radius. Eles são cortados em seu lugar.

Método 3: sombras da caixa

Podemos criar uma pequena barra (na forma do traço) usando pseudo-elementos e depois criar vários box-shadow versões para criar uma borda, como no trecho abaixo.

Se o traço tiver uma forma quadrada, um único pseudoelemento seria suficiente, mas se for um retângulo, precisaríamos de um pseudoelemento para as bordas superior + inferior e outro para as bordas esquerda + direita. Isso ocorre porque a altura e a largura do traço na borda superior serão diferentes das da esquerda.

Prós:

  1. As dimensões do traço são controláveis ​​alterando as dimensões do pseudo-elemento. O espaçamento é controlável modificando o espaço entre cada sombra.
  2. Um efeito muito exclusivo pode ser produzido adicionando uma cor diferente para cada sombra da caixa.

Contras:

  1. Como precisamos definir manualmente as dimensões do traço e do espaçamento, essa abordagem não é boa quando as dimensões da caixa pai são dinâmicas.
  2. O IE8 e inferior não suportam sombra de caixa . No entanto, isso pode ser superado usando bibliotecas como CSS3 PIE.
  3. Pode ser usado com border-radiusmas posicioná-los seria muito complicado por ter que encontrar pontos em um círculo (e possivelmente até transform).

atormentar
fonte
Se você usar a solução svg, recomendo adicionar pointer-events:noneao svg inorder para poder interagir com o conteúdo.
Sodj 6/0318
Resposta maravilhosa.
Deviance
22

Curto: Não, não é. Você terá que trabalhar com imagens.

Ham Vocke
fonte
5
esta resposta está desatualizado a partir de 2018
godblessstrawberry
2
@WilliamHampshire eu iria com esta técnica youtu.be/vs34f9FiHps?t=779 mas verifique resposta aceita, você pode gostar de outras soluções melhor
godblessstrawberry
1
@godblessstrawberry Thanks !! Mas do que está usando SVG por isso ainda não usando apenas css ...
William Hampshire
1
@WilliamHampshire há solução box-shadow no fio eu quis dizer resposta por Harry
godblessstrawberry
@godblessstrawberry Você já tentou a solução? A solução desenhou o segmento de linha tracejada por segmento. É apenas um POC e inútil na prática!
Yu Jianrong
6

Existe uma ferramenta interessante feita por @kovart chamada gerador de borda tracejada .

Ele usa um svg como imagem de fundo para permitir a configuração do traço do traço desejado, e é bastante conveniente.

Você poderia simplesmente usá-lo como a propriedade background em seu elemento no lugar da borda:

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
fonte
Esta é uma solução simples, fácil e rápida
jamesioppolo 23/06
Isso funcionou bem!
Kevin Raffay
3

O comprimento do curso depende da largura do curso. Você pode aumentar o comprimento aumentando a largura e ocultando parte da borda pelo 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
fonte
Mas dessa forma, você não poderá clicar no conteúdo do elemento original porque o pseudoelemento "after" o cobrirá. Portanto, a melhor maneira é usar SVG.
ili4 17/02
Você pode adicionar pointer-events: nonepara evitar o problema de sobreposição.
benJ
0

Recentemente, tive o mesmo problema.

Consegui resolvê-lo com duas divs absolutamente posicionadas carregando a borda (uma para horizontal e outra para vertical) e depois transformá-las. A caixa externa só precisa ser 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: usei taquiões neste exemplo, mas acho que as classes são autoexplicativas.

razzz
fonte
-1

Isso criará uma borda laranja e cinza usando a classe = "minhaclasse" na div.

.myclass {
    outline:dashed darkorange  12px;
    border:solid slategray  14px;
    outline-offset:-14px;
}
BJC
fonte
Ao "fornecer maior controle da aparência das bordas tracejadas", o OP (Pôster original) significa que ele deseja controlar o comprimento de cada traço, conforme declarado no início da pergunta. Desculpe por qualquer confusão.
Skylar