Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: CSS Quality Guide (github.com/bevacqua)
49 points by bevacqua on July 10, 2015 | hide | past | favorite | 42 comments

Great guide. I'd suggesting adding a bit more about the "why?" if the goal is compliance. In some cases, there are performance benefits to the stated approach (like not deeply nesting classes or avoiding tag based selectors) but some readers may not be aware of this and may assume that it's entirely a style based preference which is easier to ignore due to personal preference.

Ignore ID's? What? The point of an ID is it is a selector used to identify only one element on a page - A header or a footer for example. You can't replace that semantic meaning with classes, if you're only going to be using the style once on a page then change it to an ID.

Example: <div class="header inset aboutUs"> or <div id="header" class="inset aboutUs">

The difference is the second option shows at first glance what the element is supposed to be representing to someone reading your code.

This is pretty common advice and not a point of contention for front-end folks.

> if you're only going to be using the style once on a page

Herein lies the the problem. You now can't use that header anywhere else, meaning the it's non-composable. You end up writing less, and more maintainable CSS when you treat components as immutable and composable.

Most people consider the additional readability of separating out the `id` to be negligible.

It's not composable if you only write raw CSS, they're perfectly composable via @extend's and @include's, e.g.

   #login-widget {
      @extends widget();
Best of both world's, the semantic meaning of id's with the composability of classes, plus, the compiler is smart enough to reduce duplicity to it's bare minimum

But it's still not a good idea to use IDs. Why not:

   .login-widget {
      @extends widget();
The specificity that ids bring alone are good enough reason to avoid them forever. They're a sledgehammer that can pretty much only be overridden by `!important`.

If that somehow sits fine with you perhaps consider the rule the rest of the software world has accepted long ago -- 'this code will be changed'. The fact you think you will really only have one of these things on a page at once (hence making it suitable for an ID) ... that WILL change.

There will come a day when you have a login-widget in your sidebar, yet at some obscene last-minute moment the customer will demand a dedicated login page too, your developers will want to use your base template (which has your login widget visible in the sidebar) creating 2 login widgets on-page, cursing your assumption that you thought you knew better.

Ignoring that, you could forget my example above (I'm sure there's a way you could dismiss it as contrived) and learn a lesson from the OOP crowd and just never write singletons [0] ever. It's just a really bad assumption to think you'll only want one of a thing.

[0] https://en.wikipedia.org/wiki/Singleton_pattern

> You now can't use that header anywhere else, meaning the it's non-composable. You end up writing less, and more maintainable CSS when you treat components as immutable and composable.

You can use that header on any page and you're not going to re-use it on the same page. Why does it need to be "compose-able" at all?

Either way this is a silly argument because there is no problem here. You have a set of CSS styles you want applied to an element on the page that will never have a copy, etc? You can use ID or Class and you can even swap them with the same level of difficulty. This is entirely a non-issue no matter what way you go; it's more of a style thing.

When managing css in large projects, specificity is your worst enemy. ID are not styled, if there are any. If your worried about being semantic for the header and footer, use the html5 header and footer tags.

> When managing css in large projects, specificity is your worst enemy

I couldn't disagree more. The more specific you are the less side affects you'll encounter in the rest of your project. When a project gets incredibly large if your styles are NOT specific you're going to run into a lot of unintended consequences.

This doesn't mean I encourage using IDs all over the place; they should only be used when there can be a single version of that element on the page. But being specific also means using the cascade (e.g. html > body > div.mydiv versus just .mydiv).

When running a large project, there is never just a single version of a ui element. For example, using media queries, different resolutions, zoom, and print. Or if write your css in oocss with separation of concerns. Being less specific allows your css to be more manageable to change in many different situations. In complicated layouts, cascades are very non-friendly. Styling elements directly also has very high specificity.

> When running a large project, there is never just a single version of a ui element. For example, using media queries, different resolutions, zoom, and print.

Not sure why you'd make such an absolute claim. When you say single version are you saying single html element or single CSS definition? If the former then I disagree (headers, footers, main containers of content, etc), if the latter then I don't understand how this would be the case. In HTML IDs are limited to one specific element but you can refer to it as many ways as you want in CSS which means you can use different media questions, handle resolutions, print, etc.

So I'm not really sure I understand your point.

> Being less specific allows your css to be more manageable to change in many different situations. In complicated layouts, cascades are very non-friendly.

I've worked in a lot of really large projects and I'm not sure how little to no specificity could be more manageable due to side-effects. Ultimately you're going to need a mixture of specific and non-specific styling so arguing whether you should be more or less doesn't really make sense to me; just use the right level of specificity for the job at hand. If you have a page with specialized content you might want to be more specific there to not mess up another page. If you have a lot of re-usable components you probably want less.

> I couldn't disagree more. The more specific you are the less side affects you'll encounter in the rest of your project. When a project gets incredibly large if your styles are NOT specific you're going to run into a lot of unintended consequences.

You can handle 99% of use cases for specificity just nesting classes. Using IDs to settle specificity is the same as bringing an ICBM to a Nerf gun fight. When I was doing front-end development, I spent more time fighting back against overly specific CSS, thanks to IDs (and fellow developers who just sprinkled `important!` on everything until it worked), than struggling because I couldn't get specific enough without IDs.

> You can handle 99% of use cases for specificity just nesting classes.

Nesting classes can get really messy and I'm not sure that really makes sense to do in "99% of use cases" if the goal is to make something specific. Mixing classes allows you to apply multiple styles onto a single element which can be really handy but using that as the way to target a specific, single element means you can't re-use some of those classes in the same way otherwise you run the risk of targeting more than one element in the same way.

Specificity should usually be handled through the cascade and / or IDs; that's what they were meant to do. Classes provide buckets of styles as do IDs and both can be used in the same way with IDs targeting only a single element and not a compose-able one.

Ultimately you can specifically target in CSS a variety of ways. Outright saying one way is just wrong or "[an] ICBM" kinda ignores the use cases of the various ways to do it to attempt to force a single answer where I do not think a single answer is satisfactory.

I find the opposite is generally the case. I've maintained many projects which were highly specific and therefore ridged to enhancing.

I try to reuse some style to only find it doesn't work when placed somewhere else in the HTML.

Having too generic styles is also a problem though. E.g. styling a label element on the assumption it's in a form can be frustrating.

It's all about the right balance and styling specifcally what you mean, not the specific structure of the HTML.

Except in many cases, an ID can be replaced these days with an HTML5 tag that can be re-used, or with other attributes, e.g. aria ones, that mean more.

And you might run into a circumstance where you have to repeat the header or footer -- perhaps you're allowing someone to edit the header or footer of your site and you want to do so in the middle of the page? Or you want to perform a complex animation that would require having multiple elements on the page at the same time. IDs ultimately are more brittle, and they don't do anything to enforce that they're only used once on a page. Their best use appears to be for hyperlinks or perhaps actual ID numbers (e.g. JavaScript) and not much else these days, if you're being consistent.

I disagree on what this says about frameworks. I think frameworks are great. They are specially great when you come to really understand one and how it works and how it can be customised.

The major problems I've seen with frameworks is that people just use the default look or try to add customisations on top of the default CSS, overriding styles. I mean, that is just setting yourself up for a world of pain.

But most CSS frameworks are really, really flexible in the build stage. You can tweak a few variables that can dramatically alter the appearance of a stylesheet and give you an awesome base to build on. Pretty much for free.

If you do all the CSS from scratch you're anyway going to write at the least a reset, some base typographic styles, responsive stuff, and some kind of grid system. Why not use something that is widely used, peer-reviewed, and very customisable?

Just to build on top of this, and syntax-aside, what about using frameworks like SMACSS, BEM, OOCSS, etc for organizational purposes? I've been hearing a lot about these especially lately and about their greatness for scalability and maintainability once implemented and relied on.

Aren't those approaches to css rather than frameworks? I believe you can use a framework and still use those approaches to css.

Do you have a particular framework you'd recommend?

It must really depend on what you're looking for/doing. My favorite is http://getskeleton.com/. I'm a noob, but I like that I can understand and completely customize the 400 lines of code (https://github.com/dhg/Skeleton/blob/master/css/skeleton.css) easily.

I, personally, like foundation. Mostly because it's more barebones than Bootstrap, it's fairly easy to customise and it uses SCSS which I like better than Less.

On the other hand, it sometimes feels like its development has stalled, while Bootstrap future looks bright https://twitter.com/mdo/status/591364406816079873?lang=en

I like how he explains separating layout from presentation. When writing the layout code, keep in mind how its coupled to the HTML.

This link mentions how "layout" like z-index is coupled to the structure of HTML, because nesting elements creates new stacking contexts (Z-index is hierarchical - an element's z-index only controls it's depth within the current context, not the overall document). http://philipwalton.com/articles/what-no-one-told-you-about-...

This one advises using "js" prefixed classes for JS, so the JS is only coupled to the HTML & not the CSS: http://philipwalton.com/articles/decoupling-html-css-and-jav...

"Frameworks and Vendor Styles: Stay away from frameworks"

I disagree - frameworks are awesome.

I guess it's all contingent to the project you're working on though. For small projects, it speeds things up and stops you from reinventing the CSS wheel. With large projects, even if you don't use a framework, you [should] end up making one with a style guide (eg: http://walmartlabs.github.io/web-style-guide/).

Either way, to completely rule them out is not the best advice IMHO. Other than that, pretty great post/share.

Why not look at BEM?

https://en.bem.info/ http://csswizardry.com/2013/01/mindbemding-getting-your-head...

Harry Roberts really simplifies the idea of it.

This was very helpful. One thought on your "Mobile first" media queries segment. While absolutely correct in principle, those of us who unfortunately have to support IE8 should make sure to have a default style set at the "Desktop" level (ie. desktop-first) and have the @media breakpoints kick in at lower resolutions. Otherwise, they may figure out the hard way (as we did) that their webpage looks like trash on browsers that don't support media queries.

One philosophy is that if the browser is old enough to not support media queries then they should deal with the stripped down, mobile-first version of the site that they get anyway.

At that point, just create a separate IE8 stylesheet loaded with conditional comments to fix the most annoying issues so that the site is at least functional for that type of visitor. There's no reason to bloat the main stylesheet with useless crap for old versions of IE.

Most style guides say to use namespaces for everything. I've never used them. What do I have to be worried about?

If you have say a post entry:

  .post {
    border: 1px solid #000;

  .post .title {
    font-weight: bold;
And you want to put it into a sidebar

  .sidebar {
    background-color: #ccc;

  .sidebar .title {
    text-decoration: underline;
That post's title is now going to be underlined. That's one of the reasons for namespacing. If the classes were `.post--title` and `.sidebar--title`, this would be avoided

I had an explanation as to why your CSS was wrong but then I realized an HTML example is needed. I'm assuming you mean something like this:

    <section class='content'>
      <div class='post'>
        <h1 class='title'></h1>

    <section class='sidebar'>
      <div class='post'>
        <h1 class='title'></h1>
If so, what you say would indeed happen.

Also, I've never thought of .post--title as a form of namespacing. I always understood it to be more like .post .title, as in nesting with SCSS or Less. Not saying you're wrong, just never thought of it that way.

I've found that these cases are non-issues when you use something like BEM. The downside is that the HTML then becomes horrible to look at:

    <div class='sidebar'>
        <div class='sidebar__post'>
            <h2 class='sidebar__post__title'>
              Please kill me
So… you have to chose between unmaintainable CSS or weird HTML.

I think that, in the end, something like this is the only sane outcome: https://medium.com/seek-ui-engineering/the-end-of-global-css...

I probably wouldn't go so far as to use `sidebar__post__title `, just `sidebar--title` and `post--title`. That way if you want to style a post title in the sidebar, it's clearly `.sidebar .post--title`

using something like BEM solves a lot of problems. Silly collisions and searchability are my big takeaways.

Wouldn't you just instead write the CSS as follows?

  .sidebar.title {
    text-decoration: underline;

That likely wouldn't have the intended effect as I find it doubtful that the element with the sidebar class would also be the title.

Well, you could also write .sidebar > .title to be more specific than simply all .title elements in .sidebar, but the point is to not tie your CSS quite so closely to the HTML hierarchy I suppose.

If not underlining post titles is so important, than the CSS rule should make that explicit:

.post .title { font-weight: bold; text-decoration: none; }

Leaving text-decoration out of the rule is basically saying: "I defer to my ancestor rules for advice on styling this, and I accept their decision."

It's not just that the post titles shouldn't be underlined, it's that one elements style should not creep into another elements style by accident

Well, the "all descendants" selector is explicitly intended to do that. It's a bit too far to call it "by accident".

There's rarely a real use for the ".sidebar .title" construction.

Rarely? I would think the vast majority of websites would have a version of that in place in several ways.

If you use SCSS and group your CSS by, e.g. a class in the body tag and additional nesting for components, or if your component-specific styles are loaded only when necessary (e.g. HTTP/2) then not much. The purpose of these techniques, or of prefixing your class names, is to avoid naming collisions.

E.g. is your list supposed to have bullets? If you just say ul { list-style: none; } you've effectively said all lists shouldn't. But you might later say the opposite and not notice until your stylesheets are all compiled together and it's a race to see which one wins on every page.

Or the other example posted (above, since this comment was downvoted for unknown reasons) where you move HTML around and your stylesheets aren't in sync.

Of course, prefixing isn't for everyone -- e.g. https://github.com/twbs/bootstrap/issues/1235 -- some argue you should know all the styles on your page and how they interact, even if using a "CSS framework" and so naming collisions is just one of the things you'll have to worry about -- if you namespace, what's to prevent a naming collision even with your namespaces? :)

This is also where it might be useful to point to https://speakerdeck.com/vjeux/react-css-in-js

What is so bad about frameworks? Isn't a simple framework with good standard classes a good thing?

The author probaly never worked with a deadline before, where there is no time to build everything custom.

Lots of guidelines, many without an obvious reason.

I'm surprised how much the personal standards I've built up working solo for many years align with these.

Regarding "Presentation-Specific vs Layout-Specific Styles," the way I've come to organize things is roughly "outside-in" i.e.: position, margin, border, width/height, padding, font/line-height, text styles. I also always put "display" and "box-sizing" first, if they're present, since they change the effect of several things that follow.

I disagree with "Prefer nested selectors ... only if both .foo and .foo .bar need styling." I prefer nested selectors always, mostly because it's annoying to have to go back and nest something later when you realize the container needs rules, too. Also I sense that there's something beneficial about the nesting of the (in my case) scss matching the nesting of the HTML, but that might just be aesthetics.

Also disagree with "Settle for a few (2-3) breakpoints and use those only," at least for the types of designs I have to work with nowadays. The prevailing style seems to consist of a series of striking, highly independent sections with their own internal layout (think the landing page of a typical, new open source project or startup, with a hero unit or carousel, a list of features in some number of columns, testimonials in some [other] number of columns, etc.). If you make each of those sections adhere to the same handful of breakpoints, either you carefully limit your design or you risk ending up with strange looking layouts in certain sections at certain "in-between" viewport dimensions. I tend to treat each such section completely independently and use as many or as few breakpoints as necessary for that particular internal layout. Sass definitely helps with this, since nested media queries get hoisted to the top level automatically, so you can put them in a natural context.

As for mobile-first, I always work desktop-first. Part of that is that mobile-first is pretty much impossible when all you're given is a psd with a full desktop design. But I also find it completely natural to start with the desktop design, narrow the window until something looks off, throw in a media query to fix it, and repeat. And as someone else has already said, when you have to support IE8 to some degree, it's nice to have desktop as the default.

I find most of the claims in the linked article about mobile-first [1] to be hand-wavy (you don't want to include "large heavy modules by default," or in other words, you must assume that desktop-first is going to end up slow and clunky on mobile) or contrived (the actual CSS example, where you can eliminate a selector because on small devices the element in question happens to have default styles). In my experience, in fact, things are usually "heavier" on mobile, specifically because you tend to need a bunch of javascript to deal with flyout menus and things having to expand and collapse that can just be there on desktop. In any case: I don't see how the supposed benefits of mobile-first can't be had desktop-first if you just take a modicum of care in your work.

[1] http://bradfrost.com/blog/mobile/the-many-faces-of-mobile-fi...

Applications are open for YC Winter 2022

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