{"id":343613,"date":"2021-07-12T07:30:34","date_gmt":"2021-07-12T14:30:34","guid":{"rendered":"https:\/\/css-tricks.com\/?p=343613"},"modified":"2021-07-12T07:30:37","modified_gmt":"2021-07-12T14:30:37","slug":"using-the-specificity-of-where-as-a-css-reset","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/using-the-specificity-of-where-as-a-css-reset\/","title":{"rendered":"Using the Specificity of :where() as a CSS Reset"},"content":{"rendered":"\n

I don\u2019t know about you, but I write these three declarations many times in my CSS:<\/p>\n\n\n\n

ul {\n  padding: 0;\n  margin: 0;\n  list-style-type: none;\n}<\/code><\/pre>\n\n\n\n

You might yell at me and say I can just put those in my CSS resets. I wish I could, but I don\u2018t want to and I\u2019ll tell you why in a second.<\/p>\n\n\n\n\n\n\n\n

User agents set values to those properties in a list for a purpose, and that is to make lists more readable. These are the default styles in chromium browsers for a <ul><\/code> element:<\/p>\n\n\n\n

ul {\n  list-style-type: disc;\n  margin-block-start: 1em;\n  margin-block-end: 1em;\n  margin-inline-start: 0px;\n  margin-inline-end: 0px;\n  padding-inline-start: 40px;\n}<\/code><\/pre>\n\n\n\n

So, without adding any class in HTML or style in CSS, we get those for free. That\u2018s a nice thing and I don\u2018t want to lose it. But I would appreciate it if I could make the browser understand that there is very high chance I don\u2019t want that default feature in cases where I add a class to the element.<\/p>\n\n\n\n

So here is a quick solution to reset a <ul><\/code> element that has a class:<\/p>\n\n\n\n

ul[class] {\n  padding: 0;\n  margin: 0;\n  list-style-type: none;\n}<\/code><\/pre>\n\n\n\n

Now I don\u2019t lose the default style except when I add a class to my <ul><\/code> element.<\/p>\n\n\n

The problem<\/h3>\n\n\n

There is a problem with this solution. Imagine there is a list that we want to have a different list-style-type<\/code> for it, like the following:<\/p>\n\n\n\n

ul[class] {\n  padding: 0;\n  margin: 0;\n  list-style-type: none;\n}\n\n.list {\n  list-style-type: square;\n}<\/code><\/pre>\n\n\n\n

This doesn\u2019t work since ul[class]<\/code> has higher specificity. That\u2019s where our solution breaks down.<\/p>\n\n\n\n

We could add more weight to the selector\u2019s specificity:<\/p>\n\n\n\n

ul.list {\n  list-style-type: square; \/* Specificity: 0, 1, 1 *\/\n}\n\n\/* or *\/\n\n.sidebar .list {\n  list-style-type: square; \/* Specificity: 0, 2, 0 *\/\n}<\/code><\/pre>\n\n\n\n

If you are OK adding more weight to the selector, you are good to go. But I\u2019m not OK with it, personally. For example, I don\u2019t want to put the element\u2019s name in my CSS most of the times due to a separation of concerns principle. Or, if you are following BEM methodology, problems will most certainly arise as this conflicts with it.<\/p>\n\n\n\n

So what can we do?<\/p>\n\n\n

The solution<\/h3>\n\n\n

A few months ago, I learned about some hot selectors, including :is()<\/a><\/code> and :where()<\/a><\/code>. One thing about these two functional pseudo selectors, is that they can change specificity, giving us the power to nullify or increase that specificity.<\/p>\n\n\n\n

The key about :where()<\/code> is that it always has 0 specificity.<\/strong> So we can get rid of our problem very easily like this:<\/p>\n\n\n\n

:where(ul[class]) {\n  list-style: none;\n}\n\n.list {\n  list-style: square; \/* Now this works like a charm! *\/\n}<\/code><\/pre>\n\n\n\n

With the power of this selector, libraries can give us style with no specificity. So there would be no specificity to compete with when we as authors write CSS.<\/p>\n\n\n

Demo<\/h3>\n\n\n

In the following demo, you can remove :where()<\/code> to see what we talked about in action:<\/p>\n\n\n\n