Can I use the ampersand in SASS to reference speci

2019-02-02 20:55发布

问题:

This question already has an answer here:

  • Ampersand (&) at the end, and part of, a selector in SASS 1 answer

I have a class semantic which I apply to many different elements. Depending on which html tag the class is applied to, I would like it to apply a different style. This is how I tried to do it:

.semantic {
    &ul {
        padding: 0;
        margin: 0;
    }
    &p {
        margin: 0;
    }
}

This doesn't work. Of course I could write it like this, but it wouldn't be very "DRY":

 .semantic ul {
    padding: 0;
    margin: 0;
 }

 .semantic p {
     margin: 0;
 }

Is this possible?

Edit: For clarification, here is an example of what my HTML looks like:

<ul class='semantic'>
    <li>An Item</li>
</ul>

<p class='semantic'>This text is semantically a paragraph, but should not be displayed as such</p>

回答1:

What you're wanting for would in theory look like this:

.semantic {
    ul& {
        padding: 0;
        margin: 0;
    }
    p& {
        margin: 0;
    }
}

This is not possible because the & must be first. You're just going to have to deal with the fact that it isn't DRY and write it out by hand:

ul.semantic {
    padding: 0;
    margin: 0;
}

p.semantic {
    margin: 0;
}

As of Sass 3.3 or 3.4, it is possible using this syntax:

.semantic {
    ul#{&} {
        padding: 0;
        margin: 0;
    }
    p#{&} {
        margin: 0;
    }
}


回答2:

On Sass 3.4:

.semantic {
    @at-root {
      ul#{&} {
        padding: 0;
        margin: 0;
      }
      p#{&} {
        margin: 0;
      }
    }
}

Generates:

ul.semantic {
  padding: 0;
  margin: 0;
}

p.semantic {
  margin: 0;
}

@at-root moves the block to the top-level. This has several uses (see link) but here it's being used to keep take advantage of the & syntax without implying that the rules are child selectors of .semantic.



回答3:

Because of how CSS specificity works you could just do this:

.semantic {
  margin: 0; 
}

ul.semantic {
  padding: 0;
}

In your HTML, p.semantic and ul.semantic would have margin: 0; and only ul.semantic would have padding: 0;

Less Sass, less CSS. DRY.

If, unlike your example, elements on the real site have even less in common, you might want to rethink why they need to have the same class name.



回答4:

It's not quite clear what HTML structure you have.

If it's like this:

<div class="semantic">
  <p>...</p>
  <ul>...</ul>
</div>

...then you need classes like .semantic ul and .semantic p. Here's an appropriate SCSS:

.semantic {

    & ul {
        padding: 0;
        margin:  0; }

    & p {
        margin:  0; } }

If HTML structure is like this:

<p class="semantic">...</p>
<ul class="semantic">...</ul>

...then you need classes like .semantic ul and .semantic p. You should listen to bookcasey. Here's a sassy version of his DRY suggestion:

.semantic {
  padding: 0;
  margin:  0; }

p.semantic {
  margin:  0; }


标签: sass