Sass kết hợp cha mẹ bằng cách sử dụng ký hiệu và (&) với bộ chọn loại


100

Tôi đang gặp sự cố khi làm tổ trong Sass. Giả sử tôi có HTML sau:

<p href="#" class="item">Text</p>
<p href="#" class="item">Text</p>
<a href="#" class="item">Link</a>

Khi tôi cố gắng lồng các kiểu của mình vào phần sau, tôi gặp lỗi biên dịch:

.item {
    color: black;
    a& {
        color:blue;
   }
}

Làm cách nào để tham chiếu bộ chọn kiểu trước bộ chọn mẹ khi nó là một phần của cùng một phần tử?

Câu trả lời:


156

Như Kumar đã chỉ ra , điều này đã có thể xảy ra kể từ khi có Sass 3.3.0.rc.1 (Maptastic Maple).

Chỉ thị @ at-root khiến một hoặc nhiều quy tắc được phát ra ở phần gốc của tài liệu, thay vì được lồng vào bên dưới các bộ chọn cha của chúng.

Chúng ta có thể kết hợp @at-rootchỉ thị cùng với phép nội suy#{} để đi đến kết quả dự kiến.

SASS

.item {
    color: black;
    @at-root {
        a#{&} {
            color:blue;
        }
    }
}

// Can also be written like this.
.item {
    color: black;
    @at-root a#{&} {
        color:blue;
    }
}

CSS đầu ra

.item {
    color: black;
}
a.item {
    color: blue;
}

3
Đây nên là giải pháp cho câu hỏi này.
Kayhadrin

Điều này không hiệu quả với tôi ... đầu ra sắp ra mắt .item a.itemvì một số lý do. Tôi cũng đã thử tự làm a#{&}và kết quả vẫn như vậy.
jaminroe

@jaminroe bạn có đang sử dụng Libsass không? Nó sẽ được sửa trong 3.3 .
Blaine

1
@jaminroe có vẻ như nó đang sử dụng libsass (node-sass). Nếu đúng như vậy, bạn sẽ cần đợi đến 3.3.
Blaine,

1
Tôi có một phiên bản khó hơn một chút của vấn đề này để giải quyết, tương tự, nhưng với nhiều lớp, phải được thêm vào một thẻ - có ai không?
Frank Nocke

29

Các @at-rootphương pháp -only sẽ không giải quyết được vấn đề nếu bạn có ý định mở rộng selector gần nhất lên chuỗi. Ví dụ:

#id > .element {
    @at-root div#{&} {
        color: blue;
    }
}

Sẽ biên dịch thành:

div#id > .element {
    color: blue;
}

Điều gì xảy ra nếu bạn cần tham gia thẻ của mình .elementthay vì #id?

Có một chức năng trong Sass được gọi là selector-unify()giải quyết vấn đề này. Sử dụng điều này với @at-rootnó là có thể nhắm mục tiêu .element.

#id > .element {
    @at-root #{selector-unify(&, div)} {
        color: blue;
    }
}

Sẽ biên dịch thành:

#id > div.element {
    color: blue;
}

1
Điều này không mang lại cho tôi kết quả như mong đợi. Trong Sass 3.4.11, kết quả này là #id > .element #id > div.element { color: blue; }. Một cách tiếp cận khác sẽ là sử dụng selector_replace, #id { > .element { @at-root #{selector-replace(&,'.element', 'div.element')} { color: blue;}}}. Đây là một thông tin quan trọng để dễ đọc hơn.
Blaine,

@Blaine Bạn đã chọn ra một lỗi rõ ràng, cảm ơn bạn. Tôi đã chỉnh sửa câu trả lời của mình với một giải pháp hiệu quả.
Ben Fleming

1
Điều đó nói rằng, selector-replacecũng là một cách khác để làm điều đó, nhưng nó đòi hỏi phải biết bộ chọn là gì. Các selector-unifyphương pháp có lợi ích của được sử dụng trong mixins.
Ben Fleming

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

8

Đối với người mới bắt đầu, (tại thời điểm viết câu trả lời này) không có cú pháp sass nào sử dụng bộ chọn & . Nếu bạn định làm điều gì đó như vậy, bạn cần có khoảng cách giữa bộ chọn và ký hiệu và. Ví dụ:

.item {
    .helper & {

    }
}

// compiles to:
.helper .item {

}

Cách khác để sử dụng dấu và có thể là những gì bạn (không chính xác) đang tìm kiếm:

.item {
    &.helper {

    }
}

// compiles to:
.item.helper {

}

Điều này cho phép bạn mở rộng bộ chọn với các lớp khác, ID, bộ chọn giả, v.v. Thật không may cho trường hợp của bạn, điều này về mặt lý thuyết sẽ biên dịch thành một cái gì đó như .itema rõ ràng là không hoạt động.

Bạn có thể chỉ muốn nghĩ lại cách bạn đang viết CSS của mình. Có phần tử mẹ nào bạn có thể sử dụng không?

<div class="item">
    <p>text</p>
    <p>text</p>
    <a href="#">a link</a>
</div>

Bằng cách này, bạn có thể dễ dàng viết SASS của mình theo cách sau:

.item {
    p {
        // paragraph styles here
    }
    a {
        // anchor styles here
    }
}

(Lưu ý bên cạnh: bạn nên xem qua html của mình. Bạn đang trộn các dấu ngoặc kép và dấu ngoặc kép VÀ đặt thuộc tính href trên thẻ p.)


@ Lübnah Tôi đồng ý nhưng tôi không cố gắng xác định các phương pháp hay nhất để đạt được hiệu suất vi mô. Tôi đang cố gắng nhờ ai đó đang hrefgắn thẻ vào một pđể viết CSS hoạt động.
imjared

Hoàn toàn không ủng hộ việc nói & .selector là hành vi xấu, có rất nhiều trường hợp sử dụng giống như trường hợp OP đã đăng.
Mike Mellor

@MikeMellor OP đã viết .item { a& }và không có cú pháp sass nào cho điều đó (theo như tôi biết. Tôi cho rằng anh ấy có thể đang tìm kiếm thứ gì đó giống như cú pháp ký hiệu và mà bạn mô tả được sử dụng khá thường xuyên trong Sass. Tuy nhiên, xây dựng trên ví dụ của OP, .item { &a }là không hợp lệ và sẽ biên dịch để.itema .. Cũng giống như tôi đã nói trong câu trả lời của tôi là có một cái gì đó tôi đang thiếu?
imjared

OP muốn .item { a& { ... } }mà bây giờ có thể được thực hiện như @Blaine chỉ ra với .item { @at-root a#{&} { ... } }. Vấn đề là nếu bạn có một lớp trên phần tử thì nó dễ thực hiện, .item { &.class { ... } }vậy tại sao bạn không thể làm điều tương tự với một phần tử html thô. Chỉ vì không có cách nào để làm điều đó vào thời điểm OP đăng không có nghĩa là anh ấy đã sai khi muốn chức năng thực sự làm điều đó.
Mike Mellor

4

AFAIK Trong trường hợp bạn muốn kết hợp ký hiệu và cho lớp và thẻ cùng một lúc, bạn cần sử dụng cú pháp sau:

.c1 {
  @at-root h1#{&},
    h2#{&}
    &.c2, {
    color: #aaa;
  }
}

sẽ biên dịch thành

h1.c1,
h2.c1,
.c1.c2 {
  color: #aaa;
}

Các cách sử dụng khác (như sử dụng lớp trước @at-roothoặc sử dụng nhiều @at-roots) sẽ dẫn đến lỗi.

Hy vọng nó sẽ hữu ích


1
Tôi chỉ sử dụng này, rất hữu ích cho mixins nơi bạn muốn thay đổi hành vi cho tuổi hoặc div yếu tố ví dụ
santiago arizti

wow - rất tuyệt :-) Vì vậy, #{&}về cơ bản là lừa trình biên dịch - hoặc điều này sẽ luôn hoạt động trong tương lai !?
Simon_Weaver

@Simon_Weaver trong sass, mọi thứ bên trong #{}đều được đánh giá. Cũng &có nghĩa là bộ chọn hiện tại. Vì vậy, #{&}được đánh giá để .c1.
Vahid

Nhưng bạn đang lừa nó theo nghĩa & một mình không hiệu quả ;-)
Simon_Weaver

1
@Simon_Weaver xem liên kết này để biết thêm ví dụ về&
Vahid

3

Tính năng này đã có trong phiên bản mới nhất của Sass, 3.3.0.rc.1(Maptastic Maple)

Hai tính năng có liên quan chặt chẽ mà bạn sẽ cần sử dụng là có thể tập lệnh &, bạn có thể nội suy trong các kiểu lồng nhau để tham chiếu đến các phần tử mẹ và lệnh @at-root, đặt bộ chọn hoặc khối css ngay sau ở gốc (nó sẽ không có cha mẹ nào trong css đầu ra)

Xem sự cố Github này để biết thêm chi tiết

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.