Hacker News new | past | comments | ask | show | jobs | submit login
Do We Need Specificity in CSS? (2015) (philipwalton.com)
41 points by edjroot on April 17, 2020 | hide | past | favorite | 48 comments



I feel like this article is just another: "CSS is hard, and instead of learning, use this clever method that works for me."

Maybe I'm just old school because I learned CSS2 by reading the docs, and not as CSS in JS.


Not only approaching the "problem" of learning CSS by eliminating things to learn, but starting from bad assumptions (e.g. that combining stylesheets is a problem and not a solution) and never questioning them.



Oh wow, I barely remember writing this 4+ years ago!

I still hold to it - specificity is a necessary mechanism, and if it's hard, it's because we're unnecessarily over-complicating it, just like anything else considered "hard" if we misuse it.


Using SASS or LESS makes specificity a great tool

    .something { 
         .tells {
              .me {
                  content: 'we do';
              }
         }
    }
If you think of specificity as a kind of inheritance or scoping, then it makes a lot more sense.

Also it's very powerful to extend a generic component:

Framework:

    button.red { background: red; }
User code:

    button.red.disabled { background: grey; }


For me, it's actually the exact opposite. When I use scoping like that, my normal expectation is that I'm saying "Only style .me if it's in a .tells that's in a .something". I'm doing it for selector behavior. I don't want to have to consider if I later scope a

  .something_else { .me: content 'we don't' }
it won't work because it's less specific, meaning cascading isn't working as expected. It isn't SOLID


exactly. more specific selectors are edge cases, which is a usually-acceptable heuristic for rule priority but doesn't correspond 1:1.


i think the fact that specificity isn't scoped is where it causes problems.

let's say i include a CSS reset, and then include my CSS file. if i put this in my CSS file, suddenly i'm competing (and losing) against an external dependency:

    input { padding: 0.5em; }
if all CSS conflicts were resolved as "last declared wins" (rather than specificity), i feel we'd be a lot better off in terms of organized, maintainable CSS. we'd be breaking things into more files than we do today, but i think "pruning" would be a more approachable task.


Not so sure that “last declaration wins” would be great — a very specific example: jupyter notebooks (used to?) add custom.css before the original stylesheet. It’d be impossible if that were the case, I guess?


why? custom.css would still be loaded, just that if any rules conflict between the two, the original stylesheet would win.

if custom.css makes some text bold and red, and then a second stylesheet comes along and makes the text blue, the final text would be bold and blue.

but with CSS specificity defining priority, whether the text is blue or red depends on which file has the gnarliest, most complicated selector.

custom.css could be put after the original instead of before if you want the custom rules to win.


Ah, thanks for the explanation -- I thought that you meant that custom.css would be disregarded, now I see you meant that css _rules_ should use "last declaration wins".

Not really a followup on my previous question: what would be done if, say one can't change the order: so custom.css is still before original css. In such cases, without the specificity rule, wouldn't the only option we'd have is to somehow inline the styles, or spray !important everywhere?

To be clear, I only ever did this once for jupyter, and using very specific selectors was the only way I could do it -- of course I learned it hard way why this approach isn't great when jupyter changed the layout slightly. :)

If you're curious, https://github.com/prashnts/dotfiles/blob/0a2e98a848a98b7010... is that custom.css


that's true, but that's pretty much the experience of writing userstyles anyway. i remember back in the greasemonkey days, their built-in editor even had an option to automatically append `!important` to every line when you click save.


Warnings seem like the way to go for this? i.e. having a static analyzer to check that the specificity matches the declaration order. (Assuming that's possible... it's not obvious to me if there are theoretical roadblocks.)



I maintain sites with thousands of CSS rules and over a dozen style sheets, some of which are hosted on external domains that I have no control over. Having to manage CSS rules based upon order would be a nightmare.

It does seem that specificity isn't well understood, as I often see people abusing !important.


Agreed.

The article claims that "Importance also makes a lot of sense" but actually, the way it was implemented in CSS makes no sense because eventually, given a sufficiently old stylesheet, all styles end up being marked with !important and then you're back to relying on source-ordering.


Specificity and cascading become redundant once we talk css modules. I work with CSS modules so I can't remember the last time I had to_ cascade_ style sheets, or _think_ about specificity.


In my experience, very, very few Web designers actually use specificity (UPDATE: I should have added "properly," as was pointed out).

It works extremely well, if everyone follows the rules, which is uncommon.

That goes for most of CSS; not just specificity.

CSS is incredibly powerful, if used properly, and specificity, when actually used properly, is very cool.

About ten years ago, I wrote this series: https://littlegreenviper.com/miscellany/stylist/introduction...

It’s still absolutely relevant nowadays, and just as few people follow that workflow now, as they did then.

CSS, in general, is too complicated (IMNSHO), but that complexity is also what makes it so powerful.

I’ve always enjoyed Stu Nicholls’ CSSPlay site, for examples of extreme CSS: http://www.cssplay.co.uk/menu/


I find this really hard to believe. Specificity is baked into CSS at such a fundamental level that you can't not use it. Maybe you meant like they don't use it consciously of effectively?


Not the OP, but what I commonly see are elaborate behaviors by devs to try and avoid dealing with specificity head-on, because it’s so hard to reason about. In my opinion this leads to CSS that is two to three times longer than strictly necessary.

That said, I also believe that CSS was the wrong solution to the wrong job: CSS addresses the DOM, not the UI, and does so with a kind of “multiple inheritance by default” approach, where an element will inherit properties via the cascade from many rules, until a rule that stops the cascade is written. Reasoning about what rules apply to what elements under what conditions becomes an exercise in extreme abstract thinking, and still there is another step to think about what the resulting UI that it will generate will look like. (I’ll leave off browser differences for now.)


Thankfully, browser differences are reducing to a point near zero, for most "classic" CSS issues. They still have lots of differences in the way they interpret JS, though, as well as some of the newer CSS rules.

I've learned that if I keep my markup and style to "early" CSS3/HTML5, I can create pages that render pretty much the same on all browsers.

It's when I try to get fancy, that things go pear-shaped.

That said, check out CSSPlay (http://www.cssplay.co.uk/menu/). He's been pulling off extreme CSS acrobatics since CSS 1.

Amazing stuff.


One of my rules of thumb, is that “!important is FAIL.”

If I find that I need to use the !important modifier, I’m usually being lazy.

Where I do tend to use it, is in print media styles, to force a style over CMS themes, which can be notoriously bad (for example, one of the themes I have used spews out multiple duplicate #ids. When I reported the bug, the response was basically “shrug Sucks to be you.” That was the least of the issues with the theme, and I was forced to use !important a few times).


there’s using it deliberately as a tool, and running into it unexpectedly and doing absurd things to work around it like it’s an obstacle to overcome. i see much more of the latter than the former; squarely i think because most css is written by people who don’t know how to use specificity - so they come up with things like BEM, or css in js frameworks to force specificity away like it’s a flaw in the system. all this work goes in because module scope is an easier mental model to grasp than specificity, which i suppose works more like traits. but, having been in this web making game long enough, it seems like a return to table based design and font tags. just with different syntax.


Ok, just following a tangent, please let's not dismiss scopes as a clutch. They are a fundamental tool of software organization, and every large project that doesn't have scope rules ends up as spaghetti.

The fight from standard bodies against scoped CSS has lead to the current situation where every site's CSS evolves to be a mess where nobody is even sure if the rules are used, but can't delete them.


all I said was that scoping is an easier mental model than specificity. i am not saying that is a bad thing. but i can see how it would seem that way since a lot of programmers, whether they realise it or not, aggressively look down on things that are easy. so it’s essy to assume that when i say something is easier, i am implying it’s bad or weak, but i assure you i don’t mean that.


BEM I think comes from choice to aggressively reduce complexity, not from ignorance.

Sprinkled with a tiny bit of specificity classes for state, it combines best of both worlds.


then why is BEM more complex than just plain CSS? if the idea is to reduce complexity, that’s a giant fail.


It is less complex in that it eliminates specificity conflicts and approaches CSS in a modular fashion by namespacing each module/block.

You have to name things, then you don't have to apply multiple rules.


People have been freaking out about table-based design for twenty years. It’s a great foil, and much of the criticism is merited, but it’s not the end of the world.

You can fairly easily turn tables into blocks: https://littlegreenviper.com/miscellany/stylist/another-reas...

Also, I use “display: table” all the time in my work. It’s the best mode for layout that fits content.


you’re kind of missing my point. which is fine because i didn’t spend a whole lot of words explaining it.

i am not saying table based design is bad. but we did originally move away from it for legitimate reasons that seem to have been largely forgotten, and as a result we now have developers who build json theme files and react frameworks that wire “darkmode=true” individually through every component instead of just using css for what it was designed to do: to exactly be a theme configuration format.

a lot of where things have gone wrong is CSS started to be used for layout, which was originally a hack, abusing the float property to do things it was never designed to do. and css has never gotten good at it, because fundamentally layout is about relationships between elements, while CSS is stuck only ever specifying properties ON elements. sure we have display table, flexbox and css grid, but css is an incredibly awkward and unnatural way to express those concepts. app frameworks deal with layout seperately from colors and fonts, which is how it should be done. and so this is why it’s all hacks and workarounds in css land. it doesn’t have to be this way. but it’s how it is.


> a lot of where things have gone wrong is CSS started to be used for layout

The layout is part and parcel of the style. CSS gives you 7 different layout modes to choose from (normal, table, float, positioned, multi-column, flex and grid). There is more than enough here to implement any sort of layout problem you face, from using 15 year old table and flex hacks to cleaner modern approaches like flex.

> while CSS is stuck only ever specifying properties ON elements

The "position: relative" (CSS1), float and flex are all about positioning elements relative to one another. Other properties like margin, align and float are also about positioning items relative to one another.

> but css is an incredibly awkward and unnatural way to express those concepts

I think CSS is pretty easy and straightforward to reason about, once you decide that it is worth investing some time and effort in learning. It really always surprises me how some really smart people just do not get CSS, and I think it is not about ability, but attitude. CSS is dismissed as "that thing for designers", and calling CSS a programming language is usually met with smirks. That is the real problem with CSS, its reputation.


“float” and “normal” (what?) aren’t layout modes. the rest didn’t exist in css until relatively recently. postion: relative exists, yes, but it doesn’t do what you say it does. - it sets the top, left, bottom and right properties to be relative its own natural position. it doesn’t specify any relationship to any other element. the other properties you say specify layout relative other elements- don’t do what you think they do either. align and margin only effects an element’s content, margin only refers to other elements in edge cases, and float was only ever supposed to let you embed figures that text would wraparound. it’s use for layout was an abuse and not what it was designed for. Though i can see how it can seem like those elements seem like they refer to other elements, but that is just a consequence of the properties interacting with the document flow algorithm, which is there with or without css.

while css now does have real layout modules: flexbox and grid, CSS wasn’t designed for layout and it just isn’t very good at it, especially if you compare it to say, cocoa autolayout, or the flexbox model in UI frameworks that were designed to do this stuff at the start instesd of having it awkwardly bolted on. and just what is document flow? is it a layout algorithm? no, it’s a greedy word wrap algorithm applied to boxes. that’s it.

finally, 15 year old display: table and flex hacks? what are you smoking. ie8 was released in 2009 and didn’t uproot ie6 and ie7 until many years later. i had to have fallbacks for ie7 up to 2015. flex only became usable after 2015. it existed before that but not in all the browsers.

the closest thing in css to what I am talking about is position:absolute, which implicitly refers an element to its nearest parent with either position relative or position absolute. i don’t get to identify which element or elements i would like to refer to directly.

the only other thing is percentage unit which refers to a percentage of the paren’s width or height depending on which property it appears in- which was annoying enough they almost fixed it with vw and vh units which refer specifically to width and height of the viewport, but if i want a proportion of any other element’s dinensions my option is to use javascript or eat a bag of donkeys.


> “float” and “normal” (what?) aren’t layout modes.

https://developer.mozilla.org/en-US/docs/Web/CSS/Layout_mode

> the rest didn’t exist in css until relatively recently.

Out of the 7 layout modes, only the last two came into existence recently. The point is, when CSS was being designed as a declarative, domain specific programming language, it was designed to handle EVERYTHING to do with how things appear on a browser. Even when you specify styles using JS or directly in HTML, those are simple handed over to the browsers CSS engine. The HTML engine deals with markup, while the JS engine deals with behavior. If you want to talk directly and powerfully to the CSS engine, use CSS. That what it was designed to handle: everything to do with what you SEE in a browsers screen.

> position: relative exists, yes, but it doesn’t do what you say it does. - it sets the top, left, bottom and right properties to be relative its own natural position.

If I want to position elements absolutely within a container element, one way is to have the container "position: relative" and the child elements "position: absolute". The same effect can be achieved via flex or grid layouts.

> it’s use for layout was an abuse and not what it was designed for.

I am honestly flabbergasted by this assertion. The layout of something is part of its style. See https://en.wikipedia.org/wiki/Visual_design_elements_and_pri... CSS was designed to handle all that. Layout is all about shape, space and form.

> CSS wasn’t designed for layout and it just isn’t very good at it, especially if you compare it to say, cocoa autolayout, or the flexbox model in UI frameworks that were designed to do this stuff at the start instead of having it awkwardly bolted on.

Whenever anyone dumps on CSS, HTML and JS, I simply remind them that they run the web, and the web is the most successful, open, flexible and used platform in existence. CSS is doing exactly what it was designed to do, and will outlive and outperform all those UI frameworks as it breaks out of the browser into desktop and mobile app space.


look, i love CSS. Not dumping on it. but you have a bit of stockholme syndrome going on here. sometimes loving something means realistically looking at its flaws and limitations. and you seem to have a distorted view of history, and what a “stylesheet” is. (they existed for decades before CSS was invented, and come from the tradition of printing and writing, not design so much. they do not, generally speaking, specify layout. layout specifies layout.) from the start, browsers didn’t have a css engine. css was added later, and has never fully exposed every piece of the browser display engine. some of the browsers needed to be rewritten from scratch for this to even be possible. as for layout, from the start and for a very long rime, the position of the w3c and browser authors is that website authors shouldn’t want layout and refused to implement any layout capabilities. in their view, layout should be left up to the client, and a website author should focus only on writing plain semantic documents. they told people to stop using floats for layout because it got in the way of client decisions about layout. they have only been added grudgingly, and after the forced removal of the people who were blocking it. i for one welcome these layout capabilities, and am glad the old farts didn’t get in the way. that doesn’t mean we’re up to par with the best layout engines though.

your link makes only one reference to style: “style of shape”, and a passing reference to https://en.m.wikipedia.org/wiki/Style_guide with regard to keeping non layout elements consistent, and that page in turn, which makes no reference to layout.


> look, i love CSS. Not dumping on it. but you have a bit of stockholme syndrome going on here. sometimes loving something means realistically looking at its flaws and limitations.

I find that very hard to believe, sorry. And I could write a whole book about the flaws and limitations of CSS, and then another about its elegant power and gradual evolution over the years, but you most likely wont want to read it. You are stuck in 2002, completly fixated about the origins or the languange and what it was meant or not meant to do 20 years ago.

> and you seem to have a distorted view of history, and what a “stylesheet” is.

Right now, I am honestly not interested in the semantic meaning of the word "stylesheet" or its etymology, or the history of computing and printing. Am here to discuss CSS.

> from the start, browsers didn’t have a css engine. css was added later, and has never fully exposed every piece of the browser display engine.

Is this not obvious? A browser is made of three main engines JS, CSS and HTML. Being a GUI, all parts will influence the GUI. That does not change the fact that the CSS engines domain is what you see. The JS domain is interactivity (what you do with what you see) while HTML is about data and structure.

> some of the browsers needed to be rewritten from scratch for this to even be possible.

Can you name even one thing in computing that's over 20 years and has not changed or evolved? If your problem with CSS is that browsers had to be rewritten 20 years ago to evolve with the language, then that problem applies to every other successful language and GUI framework or system under the sun.

> website author should focus only on writing plain semantic documents. they have only been added grudgingly, and after the forced removal of the people who were blocking it.

Semantic documents are under the domain of HTML. This has nothing to do with CSS.


I got the point, but I found it a convenient coat hook for my favorite ulster :).

I can certainly agree with you. Some of the dynamically-generated markup can be a nightmare.

"ZenPsycho." Great screen name.


Have you worked much with mid-00's era table layouts?

There was a book written in the late 90s, which presented a method that allowed people to take a document generated in a graphics program like MM Fireworks (IIRC) and then use table rows/columns to cut up that image and create layout with more varieties of graphical elements (like using a "corner" GIF to create a rounded box).

That markup, while very useful for creating "neat" looks, was incredibly difficult to modify once it was built.

But, specifically, that's what people are railing against when they "freak out" about tables as a layout tool... not using tables for tabular data (which is, of course, just fine unless you need to reflow stuff based on screen width).


the one positive thing about table based design, is you could code a module, and just echo it out anywhere you wanted it with say, php or coldfusion, and it would mostly just work. transplanting a chunk of semantic html to a site with a different stylesheet though, if you wanted it to look the same, requires some forward planning. that is, it needs to be designed as a component, its css js and html all moved together in lockstep. and if you’re trying to be a good pure citizen, they’re in three different files and you wcho them out into the head, foot and body in turn, being careful that the js appears after anything it depends on. it would be easier to just inline the css and js and echo it all out at once, hut that will make hixie sad. and so it seems sometimes you want self contained components with all their batteries included. sometimes you want to control certain aspects of appearance in some central location so it’s easy to keep everything looking consistent. it’s not always obvious how to find the balance.


> Have you worked much with mid-00's era table layouts?

Umm... I've been designing Web sites since the mid-'90s. I used to do that very thing.

It is my shame (actually, I have many marks of shame, but we'll pretend I have just the one, for now).

That said, I also figured out how to make these "boxes" extremely flexible. I write about that in one of the links that I mentioned (https://littlegreenviper.com/miscellany/stylist/another-reas...). In that article, I describe both a "fixed," div-based "framed" table, and a flexible one; based on archaic table layout.

One advantage of having worked on sites back then (and there weren't many advantages), was that the browsers were radically different from each other, and Web designers learned to make sites that could maintain presentation in many different browsers. We generally had to do it by hand, as there wasn't really much in the way of libraries, or even prior art. We had to make it up as we went along.

I know, I know..."OK, Boomer." But it was quite helpful in understanding what was going on at the base level, and those lessons carry forward to this day.

I am not a professional Web designer. I make my own sites, and a couple of ones for NPOs, but they aren't fancy, and won't help anyone win "Buzzword Bingo." They just work fairly well, and are quite responsive.

EDITED TO ADD: You are probably thinking about this book, which became the bane of modern Web designers by the mid-oughties: https://books.google.com/books/about/Creating_Killer_Web_Sit...


Fair ‘nuff. People don’t use it consciously, so my statement was not specific enough.

:)


I feel like source order should be the thing that is done away with. Specificity allows me to style something, and trust that style will style correctly no matter what my build system does, or what order my stylesheets load, or what my co-worker adds later for their fancy new CTA button.


Nice.

Facepalm slap. Just like other matching algorithms. How did I not notice that earlier?

Order independent specificity is like longest match rules. Regex, lexing, URL routers, etc.

Order dependent matching overrides (correct phrase?) is like Packrat & PEG.

Which is better depends on ambiguity, meaning how well your "matcher" algorithm can process whatever input you have.

I've done my fair share of scraping. (I usually default to my own globbing implementation. Generally more simple than xpath or css expressions.) Now I'm feeling pretty stupid that I'd always hard-coded precedence resolution.


While this is an interesting thought experiment, and the outlined problem is a real issue, I don't think the outlined solution is a good way to resolve it. The main problem here is predictability: maybe it's simply that I'm not used to thinking about CSS this way, but the proposed CSS rewriting parser means it's not immediately obvious how what I write maps to the end result.

It's entirely possible that I'm missing some of the benefit here, but it seems to me that scoped styles etc largely already solve this problem.


The simple solution is delete before you add more specificity. Cut it back to the common denominator and cascade from there.

Of course, you can sometimes inherit a system that is one big specificity mess.


  Specificity isn’t intuitive, and—especially for new developers—the results can often seem like a gotcha rather than the intended behavior. I’m also not sure there’s an equivalent in other systems or languages.
It is widely used as a conflict resolution strategy in production systems. I've never encountered a student who found specificity to be a difficult concept to grasp.


I really admire http://tachyons.io, with its principles of shallow cascade and low specificity.

( It really sucks to have to jump in and work with some project's massive blob of vestigial, conflicting styles. )


I always write the specificity in the same order as the cascade. Could probably write a tool that compares the specificity vs the cascade to find errors!

There is however a small problem if you want to use many CSS files - that you need to link them in the correct order.

edit: Also I don't use ID's in CSS.


But what if you put your styles in multiple files?




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: