Kiểm soát độ dài nét viền đứt nét và khoảng cách giữa các nét


124

Có thể kiểm soát độ dài và khoảng cách giữa các nét viền đứt nét trong CSS không?

Ví dụ dưới đây hiển thị khác nhau giữa các trình duyệt:

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

Sự khác biệt lớn: IE 11 / Firefox / Chrome

Đường viền IE 11Viền FirefoxViền Chrome

Có bất kỳ phương pháp nào có thể cung cấp khả năng kiểm soát tốt hơn sự xuất hiện của đường viền đứt nét không?

Câu trả lời:



157

Giá trị tài sản biên giới có dấu gạch ngang bản địa không cung cấp quyền kiểm soát đối với bản thân các dấu gạch ngang ... vì vậy hãy mang border-imagetài sản vào!

Tạo đường viền của riêng bạn với border-image

Khả năng tương thích : Nó cung cấp hỗ trợ trình duyệt tuyệt vời (IE 11 và tất cả các trình duyệt hiện đại). Đường viền bình thường có thể được đặt làm dự phòng cho các trình duyệt cũ hơn.

Hãy tạo ra những

Các đường viền này sẽ hiển thị chính xác trên cùng một trình duyệt!

Ví dụ về mục tiêu Ví dụ về mục tiêu với khoảng cách rộng hơn

Bước 1 - Tạo một hình ảnh phù hợp

Ví dụ này có chiều rộng 15 pixel x chiều cao 15 pixel và khoảng trống hiện có chiều rộng 5 pixel. Nó là một .png với sự minh bạch.

Đây là những gì nó trông giống như trong photoshop khi phóng to:

Ví dụ Nền Hình ảnh Đường viền Được thổi lên

Đây là những gì nó trông giống như để mở rộng:

Hình ảnh đường viền mẫu Kích thước thực tế

Kiểm soát khoảng cách và chiều dài hành trình

Để tạo khoảng trống hoặc nét vẽ rộng hơn / ngắn hơn, hãy mở rộng / rút ngắn khoảng cách hoặc nét vẽ trong ảnh.

Đây là hình ảnh có khoảng trống rộng hơn 10px:

Khoảng cách lớn hơn được chia tỷ lệ chính xác = Khoảng cách lớn hơn để mở rộng quy mô

Bước 2 - Tạo CSS - ví dụ này yêu cầu 4 bước cơ bản

  1. Xác định biên-hình-nguồn :

    border-image-source:url("http://i.stack.imgur.com/wLdVc.png");  
  2. Tùy chọn - Xác định chiều rộng hình ảnh đường viền :

    border-image-width: 1;

    Giá trị mặc định là 1. Nó cũng có thể được đặt bằng giá trị pixel, giá trị phần trăm hoặc dưới dạng bội số khác (1x, 2x, 3x, v.v.). Điều này ghi đè bất kỳ border-widthtập hợp nào .

  3. Xác định viền-hình-lát :

    Trong ví dụ này, độ dày của các đường viền trên, phải, dưới và bên trái của hình ảnh là 2px và không có khoảng trống bên ngoài chúng, vì vậy giá trị lát cắt của chúng ta là 2:

    border-image-slice: 2; 

    Các lát trông như thế này, 2 pixel từ trên cùng, bên phải, dưới cùng và bên trái:

    Ví dụ về Slices

  4. Xác định đường viền-hình ảnh-lặp lại :

    Trong ví dụ này, chúng ta muốn mẫu lặp lại đồng đều xung quanh div của chúng ta. Vì vậy, chúng tôi chọn:

    border-image-repeat: round;

Viết tốc ký

Các thuộc tính trên có thể được đặt riêng lẻ hoặc viết tắt bằng cách sử dụng hình ảnh đường viền :

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

Hoàn thành ví dụ

Lưu ý border: dashed 4px #000dự phòng. Các trình duyệt không hỗ trợ sẽ nhận được đường viền này.

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


Lưu ý rằng bạn cần chỉ định border-style: solid(hoặc điều gì đó tương tự) nếu bạn bỏ qua dự phòng.
Robbendebiene

Giải pháp này không hoạt động với thuộc tính 'border-color'
Michael Rovinsky

102

Ngoài thuộc border-imagetính, có một số cách khác để tạo đường viền đứt nét với quyền kiểm soát độ dài của nét vẽ và khoảng cách giữa chúng. Chúng được mô tả dưới đây:

Phương pháp 1: Sử dụng SVG

Chúng ta có thể tạo đường viền đứt nét bằng cách sử dụng một pathhoặc một polygonphần tử và thiết lập thuộc stroke-dasharraytính. Thuộc tính nhận hai tham số trong đó một tham số xác định kích thước của dấu gạch ngang và tham số kia xác định khoảng cách giữa chúng.

Ưu điểm:

  1. SVG về bản chất là đồ họa có thể mở rộng và có thể thích ứng với bất kỳ kích thước vùng chứa nào.
  2. Có thể hoạt động rất tốt ngay cả khi có border-radiusliên quan. Chúng tôi chỉ cần thay thế pathbằng một circlenhư trong câu trả lời này (hoặc) chuyển đổi paththành một vòng tròn.
  3. Hỗ trợ trình duyệt cho SVG là khá tốt và dự phòng có thể được cung cấp bằng VML cho IE8-.

Nhược điểm:

  1. Khi các kích thước của vùng chứa không thay đổi theo tỷ lệ, các đường dẫn có xu hướng mở rộng quy mô dẫn đến thay đổi kích thước của dấu gạch ngang và khoảng cách giữa chúng (hãy thử di chuột vào hộp đầu tiên trong đoạn mã). Điều này có thể được kiểm soát bằng cách thêm vector-effect='non-scaling-stroke'(như trong hộp thứ hai) nhưng hỗ trợ của trình duyệt cho thuộc tính này là con số không trong IE.


Phương pháp 2: Sử dụng Gradients

Chúng ta có thể sử dụng nhiều linear-gradientảnh nền và đặt chúng một cách thích hợp để tạo hiệu ứng đường viền đứt nét. Điều này cũng có thể được thực hiện với a repeating-linear-gradientnhưng không có nhiều cải thiện vì sử dụng gradient lặp lại vì chúng ta cần mỗi gradient lặp lại theo một hướng.

Ưu điểm:

  1. Có thể mở rộng và có thể thích ứng ngay cả khi kích thước của vùng chứa là động.
  2. Không sử dụng bất kỳ phần tử giả bổ sung nào có nghĩa là chúng có thể được giữ lại cho bất kỳ mục đích sử dụng tiềm năng nào khác.

Nhược điểm:

  1. Hỗ trợ của trình duyệt đối với gradient tuyến tính tương đối thấp hơn và đây là điều không nên làm nếu bạn muốn hỗ trợ IE 9-. Ngay cả các thư viện như CSS3 PIE cũng không hỗ trợ tạo các mẫu gradient trong IE8-.
  2. Không thể sử dụng khi border-radiuscó liên quan vì nền không dựa trên đường cong border-radius. Thay vào đó, họ bị cắt bớt.

Phương pháp 3: Bóng hộp

Chúng ta có thể tạo một thanh nhỏ (trong hình dạng của dấu gạch ngang) bằng cách sử dụng các phần tử giả và sau đó tạo nhiều box-shadowphiên bản của nó để tạo đường viền như trong đoạn mã dưới đây.

Nếu dấu gạch ngang là hình vuông thì một phần tử giả duy nhất là đủ nhưng nếu nó là hình chữ nhật, chúng ta sẽ cần một phần tử giả cho các đường viền trên + dưới và một phần tử giả khác cho các đường viền trái + phải. Điều này là do chiều cao và chiều rộng của dấu gạch ngang trên đường viền trên cùng sẽ khác với chiều cao ở bên trái.

Ưu điểm:

  1. Kích thước của dấu gạch ngang có thể kiểm soát được bằng cách thay đổi kích thước của phần tử giả. Khoảng cách có thể được kiểm soát bằng cách sửa đổi khoảng cách giữa mỗi bóng.
  2. Một hiệu ứng rất độc đáo có thể được tạo ra bằng cách thêm một màu khác nhau cho mỗi bóng hộp.

Nhược điểm:

  1. Vì chúng ta phải đặt kích thước của dấu gạch ngang và khoảng cách theo cách thủ công, nên cách tiếp cận này không tốt khi kích thước của hộp mẹ là động.
  2. IE8 trở xuống không hỗ trợ bóng hộp . Tuy nhiên, điều này có thể được khắc phục bằng cách sử dụng các thư viện như CSS3 PIE.
  3. Có thể được sử dụng với border-radiusnhưng việc định vị chúng sẽ rất khó khăn với việc phải tìm các điểm trên một vòng tròn (và thậm chí có thể transform).


Nếu bạn định sử dụng giải pháp svg, tôi khuyên bạn nên thêm pointer-events:nonevào svg inorder để có thể tương tác với nội dung.
Sodj

Câu trả lời tuyệt vời.
Deviance

22

Ngắn gọn: Không, không phải đâu. Thay vào đó, bạn sẽ phải làm việc với hình ảnh.


5
câu trả lời này đã lỗi thời kể từ năm 2018
godblessstrawberry

2
@WilliamHampshire tôi sẽ đi với kỹ thuật này youtu.be/vs34f9FiHps?t=779 nhưng kiểm tra câu trả lời được chấp nhận, bạn có thể muốn các giải pháp khác tốt hơn
godblessstrawberry

1
@godblessstrawberry Cảm ơn !! Nhưng nhân đó là sử dụng SVG nên vẫn không sử dụng chỉ css ...
Kyle Krzeski

1
@WilliamHampshire có giải pháp hộp bóng trong thread Tôi có nghĩa là câu trả lời của Harry
godblessstrawberry

@godblessstrawberry Bạn đã thử giải pháp chưa? Giải pháp vẽ đoạn thẳng đứt đoạn theo từng đoạn. Nó chỉ là một POC và vô dụng trong thực tế!
Yu Jianrong

6

Có một công cụ thú vị do @kovart tạo ra được gọi là trình tạo đường viền đứt nét .

Nó sử dụng svg làm hình nền để cho phép thiết lập mảng nét gạch ngang mà bạn mong muốn và khá tiện lợi.

Sau đó, bạn chỉ cần sử dụng nó làm thuộc tính nền trên phần tử của mình thay cho đường viền:

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

Đây là một giải pháp đơn giản, dễ dàng và nhanh chóng
jamesioppolo

Điều này hoạt động tốt!
Kevin Raffay

3

Chiều dài nét vẽ phụ thuộc vào độ rộng nét vẽ. Bạn có thể tăng chiều dài bằng cách tăng chiều rộng và ẩn một phần đường viền bằng phần tử bên trong.

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


Nhưng bằng cách này, bạn sẽ không thể nhấp vào nội dung của phần tử gốc vì ký hiệu giả "sau" sẽ che nó. Vì vậy, cách tốt nhất là sử dụng SVG.
ili4

Bạn có thể thêm pointer-events: noneđể ngăn vấn đề lớp phủ.
benJ

0

Tôi vừa mới gặp vấn đề tương tự.

Tôi đã giải quyết nó bằng hai div được định vị tuyệt đối mang đường viền (một cho chiều ngang và một cho chiều dọc), và sau đó biến đổi chúng. Hộp bên ngoài chỉ cần định vị tương đối.

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

Lưu ý: tôi đã sử dụng tachyon trong ví dụ này, nhưng tôi đoán các lớp này là loại tự giải thích.


-1

Điều này sẽ tạo ra một đường viền màu cam và màu xám bằng cách sử dụng class = "myclass" trên div.

.myclass {
    outline:dashed darkorange  12px;
    border:solid slategray  14px;
    outline-offset:-14px;
}

Bằng cách "cung cấp khả năng kiểm soát tốt hơn sự xuất hiện của các đường viền đứt nét", OP (Original Poster) có nghĩa là anh ta muốn kiểm soát độ dài của mỗi dấu gạch ngang, như đã nêu ở đầu câu hỏi. Xin lỗi vì bất kỳ sự nhầm lẫn nào.
Skylar
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.