Kontroluj długość pociągnięcia kreskowanej granicy i odległość między pociągnięciami

124

Czy można kontrolować długość i odległość między kreskowanymi kreskami w CSS?

Poniższy przykład wyświetla się inaczej w różnych przeglądarkach:

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

Duże różnice: IE 11 / Firefox / Chrome

Obramowanie IE 11Firefox BorderObramowanie Chrome

Czy są jakieś metody, które mogą zapewnić większą kontrolę nad wyglądem przerywanych granic?

AntonAL
źródło

Odpowiedzi:

157

Wartość nieruchomości w rodzimej przerywanej granicy nie zapewnia kontroli nad samymi kreskami ... więc przynieś border-imagenieruchomość!

Zaparz własną granicę z border-image

Kompatybilność : Oferuje doskonałą obsługę przeglądarek (IE 11 i wszystkie nowoczesne przeglądarki). Normalne obramowanie można ustawić jako rezerwę dla starszych przeglądarek.

Stwórzmy je

Te obramowania będą wyświetlać dokładnie to samo w różnych przeglądarkach!

Przykład celu Przykład celu z większymi lukami

Krok 1 - Utwórz odpowiedni obraz

Ten przykład ma 15 pikseli szerokości i 15 pikseli wysokości, a przerwy mają obecnie szerokość 5 pikseli. Jest to plik .png z przezroczystością.

Tak to wygląda w Photoshopie po powiększeniu:

Przykładowe tło obrazu obramowania wysadzone w górę

Oto jak wygląda skalowanie:

Przykład rzeczywisty rozmiar tła obrazu obramowania

Kontrolowanie odstępu i długości skoku

Aby utworzyć szersze / krótsze przerwy lub kreski, poszerz / skróć przerwy lub kreski na obrazie.

Oto obraz z szerszymi przerwami 10px:

Większe luki poprawnie wyskalowane = Większe luki w skali

Krok 2 - Utwórz CSS - ten przykład wymaga 4 podstawowych kroków

  1. Zdefiniuj border-image-source :

    border-image-source:url("http://i.stack.imgur.com/wLdVc.png");  
  2. Opcjonalnie - zdefiniuj border-image-width :

    border-image-width: 1;

    Wartość domyślna to 1. Można ją również ustawić za pomocą wartości piksela, wartości procentowej lub jako inną wielokrotność (1x, 2x, 3x itd.). To przesłania dowolny border-widthzestaw.

  3. Zdefiniuj border-image-slice :

    W tym przykładzie grubość górnej, prawej, dolnej i lewej krawędzi obrazów wynosi 2 piksele, a poza nimi nie ma przerwy, więc wartość naszego wycinka to 2:

    border-image-slice: 2; 

    Plasterki wyglądają tak, 2 piksele od góry, prawej, dołu i lewej:

    Przykład plastrów

  4. Zdefiniuj powtarzanie obramowania obrazu :

    W tym przykładzie chcemy, aby wzorzec powtarzał się równomiernie wokół naszego elementu div. Więc wybieramy:

    border-image-repeat: round;

Pisanie stenografii

Powyższe właściwości można ustawić indywidualnie lub w skrócie za pomocą border-image :

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

Kompletny przykład

Zwróć uwagę na border: dashed 4px #000rezerwę. Nieobsługiwane przeglądarki otrzymają tę ramkę.

.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
źródło
Zauważ, że musisz określić border-style: solid(lub coś podobnego), jeśli pominiesz rezerwę.
Robbendebiene
To rozwiązanie nie działa z atrybutem „border-color”
Michael Rovinsky
102

Oprócz border-imagewłaściwości istnieje kilka innych sposobów tworzenia przerywanej granicy z kontrolą długości pociągnięcia i odległości między nimi. Zostały opisane poniżej:

Metoda 1: Korzystanie z formatu SVG

Kreskowaną ramkę możemy utworzyć, używając elementu pathlub a polygoni ustawiając stroke-dasharraywłaściwość. Właściwość przyjmuje dwa parametry, z których jeden określa rozmiar myślnika, a drugi określa odstęp między nimi.

Plusy:

  1. Pliki SVG z natury są skalowalną grafiką i można je dostosować do dowolnych wymiarów kontenera.
  2. Może działać bardzo dobrze, nawet jeśli jest border-radiuszaangażowany. W tej odpowiedzi po prostu zastąpilibyśmy pathznak „ circlelike” (lub) zamieniając go na okrąg.path
  3. Wsparcie przeglądarek dla SVG jest całkiem dobre, a rezerwę można zapewnić używając VML dla IE8-.

Cons:

  1. Gdy wymiary pojemnika nie zmieniają się proporcjonalnie, ścieżki mają tendencję do skalowania, co powoduje zmianę rozmiaru kreski i odstępu między nimi (spróbuj najechać kursorem na pierwsze pole we fragmencie). Można to kontrolować, dodając vector-effect='non-scaling-stroke'(jak w drugim polu), ale przeglądarka nie obsługuje tej właściwości w IE.


Metoda 2: Korzystanie z gradientów

Możemy użyć wielu linear-gradientobrazów tła i odpowiednio je ustawić, aby uzyskać efekt przerywanej granicy. Można to również zrobić repeating-linear-gradientza pomocą gradientu, ale nie ma dużej poprawy, ponieważ używa się powtarzającego się gradientu, ponieważ każdy gradient powinien być powtarzany tylko w jednym kierunku.

Plusy:

  1. Skalowalne i można je dostosowywać, nawet jeśli wymiary kontenera są dynamiczne.
  2. Nie wykorzystuje żadnych dodatkowych pseudoelementów, co oznacza, że ​​można je odłożyć na bok do jakiegokolwiek innego potencjalnego użycia.

Cons:

  1. Obsługa gradientów liniowych w przeglądarkach jest stosunkowo niższa i nie jest to możliwe, jeśli chcesz obsługiwać IE 9-. Nawet biblioteki, takie jak CSS3 PIE, nie obsługują tworzenia wzorów gradientów w IE8-.
  2. Nie można użyć, gdy border-radiusjest zaangażowany, ponieważ tła nie są zakrzywione na podstawie border-radius. Zamiast tego są przycinane.

Metoda 3: Cienie w pudełku

Możemy stworzyć mały pasek (w kształcie myślnika) za pomocą pseudoelementów, a następnie stworzyć wiele jego box-shadowwersji, aby stworzyć obramowanie jak na poniższym fragmencie.

Jeśli kreska ma kształt kwadratu, wystarczy jeden pseudoelement, ale jeśli jest to prostokąt, potrzebowalibyśmy jednego pseudoelementu na górną i dolną krawędź, a drugiego na lewą i prawą krawędź. Dzieje się tak, ponieważ wysokość i szerokość kreski na górnej krawędzi będą inne niż po lewej stronie.

Plusy:

  1. Wymiary myślnika można kontrolować, zmieniając wymiary pseudoelementu. Odstępy można kontrolować, modyfikując przestrzeń między każdym cieniem.
  2. Bardzo wyjątkowy efekt można uzyskać, dodając inny kolor dla każdego cienia w pudełku.

Cons:

  1. Ponieważ musimy ręcznie ustawić wymiary kreski i odstępów, to podejście nie jest dobre, gdy wymiary ramki nadrzędnej są dynamiczne.
  2. IE8 i starsze nie obsługują cienia skrzynek . Można to jednak obejść, używając bibliotek, takich jak CSS3 PIE.
  3. Można ich używać z, border-radiusale ich pozycjonowanie byłoby bardzo trudne w przypadku konieczności znalezienia punktów na okręgu (a może nawet transform).

Złupić
źródło
Jeśli zamierzasz używać rozwiązania SVG, radzę dodać pointer-events:nonedo SVG w celu umożliwienia interakcji z zawartością.
Sodj
Cudowna odpowiedź.
Deviance
22

Krótko mówiąc: nie, nie jest. Zamiast tego będziesz musiał pracować z obrazami.

Ham Vocke
źródło
5
ta odpowiedź jest nieaktualna na rok 2018
godblessstrawberry
2
@WilliamHampshire Wybrałbym tę technikę youtu.be/vs34f9FiHps?t=779, ale sprawdź zaakceptowaną odpowiedź, inne rozwiązania mogą Ci się bardziej
spodobać
1
@godblessstrawberry Thanks !! Ale to używa SVG, więc nadal nie używam tylko css ...
Kyle Krzeski
1
@WilliamHampshire W wątku, o którym miałem na myśli odpowiedź Harry'ego, jest rozwiązanie typu box-shadow
godblessstrawberry
@godblessstrawberry Czy wypróbowałeś rozwiązanie? Rozwiązanie narysowało przerywaną linię segment po segmencie. To tylko POC i bezużyteczne w praktyce!
Yu Jianrong
6

Jest fajne narzędzie stworzone przez @kovart o nazwie generator przerywanej granicy .

Używa svg jako obrazu tła, aby umożliwić ustawienie żądanej tablicy kresek obrysu i jest całkiem wygodne.

Następnie użyłbyś go po prostu jako właściwości tła w swoim elemencie zamiast obramowania:

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
źródło
To proste, łatwe i szybkie rozwiązanie
jamesioppolo
To działało dobrze!
Kevin Raffay
3

Długość pociągnięcia zależy od szerokości pociągnięcia. Możesz zwiększyć długość, zwiększając szerokość i ukryć część obramowania za pomocą elementu wewnętrznego.

.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
źródło
Ale w ten sposób nie będziesz w stanie kliknąć zawartości oryginalnego elementu, ponieważ pseudoelement „po” go zakryje. Najlepszym sposobem jest więc użycie SVG.
ili4
Możesz dodać, pointer-events: noneaby zapobiec problemowi z nakładką.
BenJ
0

Niedawno miałem ten sam problem.

Udało mi się to rozwiązać z dwoma absolutnie ustawionymi divami niosącymi obramowanie (jeden dla poziomej i jeden dla pionu), a następnie je przekształcić. Po prostu zewnętrzne pudełko musi być ustawione względnie.

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

Uwaga: w tym przykładzie użyłem tachionów, ale wydaje mi się, że te zajęcia nie wymagają wyjaśnień.

razzz
źródło
-1

Spowoduje to utworzenie pomarańczowo-szarej ramki przy użyciu class = "myclass" elementu div.

.myclass {
    outline:dashed darkorange  12px;
    border:solid slategray  14px;
    outline-offset:-14px;
}
BJC
źródło
Poprzez „zapewnienie większej kontroli nad wyglądem przerywanej granicy” OP (oryginalny plakat) oznacza, że ​​chce kontrolować długość każdej kreski, jak stwierdzono na początku pytania. Przepraszamy za zamieszanie.
Skylar