tomhodgins / element-queries-spec

A spec for a Container-Style Element Query Syntax
https://tomhodgins.github.io/element-queries-spec/element-queries.html
367 stars 14 forks source link

Specificity #5

Closed richardbushell closed 7 years ago

richardbushell commented 7 years ago

I am right in understanding that EQCSS will always create a real CSS Rule with just a single [data-attribute] selector (irrespective of the selector used as the EQCSS selector)? e.g. (at)element '#specific.ew' { $this { font-size: 2ew; } } will always give [data-eqcss-0-0] {font-size: 2ew;}; and NEVER:

specific.ew.[data-eqcss-0-0] {font-size: 2ew;};

Do I understand that correctly?

Is there any way to 'pass through' the selector to make it more SPECIFIC?

At the moment we have potential issues where greater Specificity exists for some elements within existing CSS stylesheets, or if we wanted to provide a standard CSS fallback just in case.

At the moment the only solution I can find is to include !important for all the EQCSS rules.

Please advise.

tomhodgins commented 7 years ago

Hi @richardbushell! Thanks for taking a peek at EQCSS. You're right about EQCSS assigning data attributes to the scoped elements so it can remember which ones they are, and outputting the result of meta-selectors like $this to an attribute that looks something like [data-eqcss-1-0].

I've written a natural progression of specificity from less specific to more specific (all without using !important) so you can see how you can beef up your selectors without using !important to override existing styles.

The main thing here is to remember that #example shorthand always wins over attributes, even [id=example] which selects an element based on its id, but using the attribute selector. All of the selectors EQCSS writes by itself are at that attribute selector level of strength.

<div id=example>Text</div>

<style>
  div {
    background: red;
  }

  /* stronger than 'div' */
  /* attribute selector beats tag name */
  @element 'div' {
    $this {
      background: lime;
    }
  }

  @element '#example' {
    /* equal in strength to @div $this */
    /* attribute selector equal to attribute selector */
    $this {
      background: purple;
    }
  }

  /* stronger than 'div' or @div $this */
  /* ID selector beats any attribute selector */
  #example {
    background: orange;
  }

  @element 'div' {
    /* stronger than @div $this or @#example $this */
    /* attribute plus ID selector beats attribute selector */
    $this#example {
      background: pink;
    }
  }

  @element '#example' {
    /* equal in strength to @div $this#example */
    /* attribute plus ID selector equal to attribute plus ID selector */
    $this#example {
      background: aqua;
    }
  }
</style>

<script src=http://elementqueries.com/EQCSS.js></script>

So in this test case, if you start at the bottom and move the background colors (or comment them out) each time you'll see the rule above it being displayed. Some selectors I've marked as equal strength - these you can rearrange the order of and you'll always see the last result as the style is read from top to bottom, but for ones where the selector is stronger the other doesn't matter, it will always win no matter where it's located in your stylesheet!

the TL;DR is that if you know something like $this is being output like [data-eqcss-1-0] then you can think of a selector like $this#example as being equivalent to [data-eqcss-1-0]#example :)

Does that help clear up the specificity issue?

richardbushell commented 7 years ago

@tomhodgins Thanks, that answers my query perfectly. Sorry, for some reason I hadn't considered that you could add other selectors to the EQCSS Rule Part if using $this. Using either: $this#specific

specific$this

solves my problem perfectly without ever needing !important. Again, not being used to $this, I simply hadn't considered a syntax combining $this with other selectors as normal. May I congratulate you on a great body of work! Really impressive!

p.s one other question if I may, as it's not really an issue, just advice... If we want to style font-sizes in paragraph p tags (which are width 'auto' by default) but based on the width of the parent container of those p tags, then I assume we'd be best to set a 'font-size' (using EQCSS) selected directly on the PARENT container and using it's own width, and then use 'em' units for relative font-sizes of all p tags within it. Is that the best way? Still getting my head around the 'element-level queries'.

tomhodgins commented 7 years ago

Which property are you trying to set on the <p> inside a container @richardbushell?

If you want to set the font-size of the <p> elements inside a containing element to a size that's based on that parent element's own width, there is a way with EQCSS using ew units, a new unit we invented to be similar to vw or vh units, but relative to the Element Width instead of the Viewport Width

A very basic use of this might be:

<section>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</section>

<style>
  @element 'section' {
    $this p {
      font-size: 3ew;
    }
  }
</style>

<script src=http://elementqueries.com/EQCSS.js></script>

If I had to explain that query in prose I'd say:

If there is at least one section element present in HTML, for any element that matches the tag name section, for every <p> tag inside each matching element set the font size to 3% of the section element's width as it appears on the page.

For more demos of ew, eh, emin, and emax units check out:

And for more reading about how the style scoping works check out: How Style Scoping Works with Element Queries which might clear up a few things. There's also the technical documentation from v1 which explains how the plugin interprets the syntax and applies the styles.

Also, one last link is to the documentation for the element-based units

Does that answer the font-size question? Using these new concepts can be a little hard to wrap your head around at first but the power and flexibility you gain is hard to go back from once you've used it :D

Let me now if you have any other questions or ideas, and feel free to drop by the EQCSS chat room any time for dialogue as well!

richardbushell commented 7 years ago

@tomhodgins Thanks, perfect answer. I hadn't considered that the 'ew' units were set based on the '@element selector' rather than the 'Rule selector' element. That is so simple! Thanks so much. My life in the 'responsive' world is now so much easier due to your great work... Case closed.