Hacker News new | past | comments | ask | show | jobs | submit login
CSS: The bad bits and how to avoid them (joeforshaw.com)
161 points by jofo25 on March 19, 2018 | hide | past | favorite | 105 comments



There's nothing wrong with styling on an id.

You could put the style right in the HTML tag, or on the page where it's used, but with dynamic pages (and static stylesheets) both options will cost you bandwidth.

And they split up your styles into separate places.

So putting the style on the id is the right thing to do, and I don't understand why the author is against it.

If I need my footer to look a certain way, then #footer {} is exactly what you should do.

Not add some bogus class based style just in case someone decides we need two footers on one page.


There is not a single time I had though to myself "This should have been an ID instead of a class"; but there are hundreds of times where I have though to myself "This should have been a class instead of an ID".


Interesting, I'm the other way around, I've defaulted to classes and then found that Ids would be more appropriate in many cases.

My simple rule for id vs class (as a non-expert) is if you say 'this is the x' e.g. 'this is the footer/header/navigation-panel' then it's an Id, if you would say 'this is a y' e.g. 'this the a product/list-item/image' then it's a class.


In terms of pure CSS it doesn't matter, but for JavaScript that manipulates the DOM (e.g. jQuery), it does. Specifically, `getElementById` is more than 50% faster than `getElementsByClassName`.

https://jsperf.com/id-vs-class-hn/1


That micro benchmark is comparing getElementById which is a map lookup (assuming the id is unique in the document) vs getElementsByClassName which is creating an iterator that would scan the document as you loop over it, except that the page is not looping over it or calling .length, so it's not really scanning anything at all.

Essentially it's benchmarking a handful of branches inside getElementById that do the map lookup for an Element [1] against the handful of branches inside getElementsByClassName that do the map lookup for a NodeList [2]. They both look pretty similar to me in branch and map lookup count, so I'm not sure where the difference is, but it's not something that would impact real content since on a real page getElementsByClassName's cost is related to typical behavior being O(N) instead of O(1) like getElementById. Browsers have a ton of caching around it though, so getElementsByClassName can look like O(1) in micro benchmarks.

You could could alter the benchmark to do getElementsByClassName("my-class")[0] to test the scanning but browsers cache that too, so you'd need to actually modify the document between each run of the benchmark somehow (ex. adding or removing an element) to invalidate the cache.

Typical content that uses getElementById will be faster than content that uses getElementsByClassName, but it's hard to show that in a benchmark. :)

[1] https://cs.chromium.org/chromium/src/third_party/WebKit/Sour...

[2] https://cs.chromium.org/chromium/src/third_party/WebKit/Sour...


Well if what you style is the main content/header/footer area, and there is should only be one of it per page, using an id is a good way to enforce it as well as document it.

If you made it a class, I would assume I can reuse it elsewhere.

Now it's ony true for stuff you can't reuse, but unless you are building a boostrap competitors, there are actually a lot of things you never reuse in a real website.


Once I needed to make an internal IE addon to listen for certain elements being selected on pages outside of our control. (to ensure we never collected sensitive data for compliance reasons, long story. Trust me it makes more sense in context than it does in a single paragraph.)

My co-worker wanted to grab by id and attach listeners, but I was convinced that wouldn't work. I wanted to listen at the top level and filter down by id/class/etc...

The first production test was <redacted>.com/login. It had a login widget on the navbar and a login widget in the main content section. Both the username and the password field had the same id in the navbar and the content. So the addon did the right thing on the navbar, but not in the content, and we had to go back and redo it thanks to id reuse.

My point is, elements with ids are rarely unique. I've never regretted using a class instead of an id. I've regretted using an id instead of a class. And I really regretted third parties using ids instead of classes.

Please don't use ids. Your unique elements won't be for long, I guarantee it.


A friend once told me about a girl in their cs 101 class, who learned about arrays, and proceeded to make every variable an array. When queried, she responded, "I might end up realizing I need a multiple of the variable, and this way I won't have to change anything when I do".


Did she then go on to create jQuery? Because that concept (with a touch of functional inspiration) is one of the underlying ideas behind the library and why it was considered so much easier to work with than the DOM API.

I get where you're coming from, but I don't think it's a good reason to avoid classes. That's what they're there for.


Not at all; some simple effects like a stick-to-the-top header usually require cloning such element using JavaScript; and even if such effects are not needed right now they may be added in the near future, so no, there is not a single time where having an ID over a class makes sense.


Since I'm more of a backend dev, I'm going to take your advice and try it on my next work. Let's learn something today.


I tend to reserve IDs for things that exist only once on the page at a given time, and the only properties I define under IDs are ones for layout. For example, if I have a page for an article, I would make the top-most element "#article" and things like the navbar and the body "#article__nav" and "#article_body". The only thing those IDs are concerned with is how the navbar and the body are sized and positioned when on the article page.

Shared stylistic properties for components use class names. The properties that make a navbar look like a navbar(color, font, and anything that applies to children) would be specified under ".nav" and the same would apply for the body under ".body". Anything that's stylistically-specific to

Shared variations of components are handled with modifiers. An example would be ".nav--dark".

Any one-off variations are handled with parent-scoped class names like ".article__nav", since I treat even that topmost element as a component. (or a block if you're thinking in BEM).

I've found that keeping "style" and "layout" CSS properties separate helps keep components flexible and untangled from a given page layout. The differentiation between IDs and class names makes this more convenient because it becomes obvious what parts of my CSS are intended for.

But what about the internal layout of components? If the children of a component are supposed to change their sizing and positioning at different breakpoints, then how are you supposed to achieve this while keeping components agnostic about the page layout?

It's a tricky problem, but I solve this with Sass mixins. If a component has different internal layouts for mobile and tablet screens, as an example, I write mixins to define those states using the same naming convention that I would use with class names and IDs. If I was using a grid system, I would define them as "@nav--lg", "@nav--md", "@nav--sm", "@nav--xs", etc. Then underneath the page layout, in this case "#article", I would include those mixins under the chosen breakpoints. That way, all layout can be handled by IDs in stylesheets dedicated to page layouts.

It just so happens that I have a Codepen that demonstrates this idea:

https://codepen.io/Ravenstine/pen/xpYoWv

The only part that is different is that I made the masthead and the footer not a part of "#article". If you don't plan on having components like that behave differently depending on the page they are on, that's probably appropriate.


I think the author probably agrees with you. What you pointed out is the exception to the rule though. The percentage of things on a page that are "singletons" is very small compared to reusable widgets.

If you don't have much resuable stuff on your site, that's a code smell in itself


> If you don't have much resuable stuff on your site, that's a code smell in itself

It can be reusable and yet unique on each page. And those should get id's, and are not rare at all.

> The percentage of things on a page that are "singletons" is very small compared to reusable widgets.

That isn't necessarily true. Obviously there are different types of pages, but a typical page will have a number of elements on it that are each unique. (They might appear on more than one page, but on any particular page, they are unique.)

Give them id's, that's what they are for.


> It can be reusable and yet unique on each page. And those should get id's, and are not rare at all.

I _think_ what's going on here is that, in the, excuse my French, _enterprise_ sector it's very common to have some sort of an end-user configurable, enormous form (or dashboard or whatever) full of widgets that are not in any way unique. In fact in many places it's so common, that for a certain section of developers it might be hard to imagine that the opposite is actually quite common.

This is _a lot_ of "web" development. Often done by developers who, to be honest, would rather be doing this in QT (eww) or something.


Elements can often be unique today but not tomorrow as pages grow in complexity and start sharing features. Ids are fine (even necessary) for things that are unique in their very essence, like a label's for="", the target for a URL fragment, or things that need special individualized treatment in JavaScript. In the common "unique today" case, ids provide no benefit over classes as simple styling hooks and quickly become a PITA when they start colliding.


In the classic days of web dev it was best practice (and still is in my opinion) to separate style (CSS) from functionality (JavaScript). So you had classes for CSS and id's for JS. So if you change the id you don't have to update your CSS. If you have a "singleton" it's better to use the element's name instead of id in the CSS. for example body instead of #body for the same reason (separate from JS). And if you want to have different types of body, add a class to the special body. id's will for example create global JS variables, so if you are styling using #id you will create a bunch of unnecessary global JS variables.


Sure, the author is describing good practice, not best practice.

If you have a choice, use class, then if you need to modify a specific use of the class, use id.

I would still use .footer instead of #footer. Of course you should consider <footer> as well.


You can have many classes!!

  <div class="footer special enterprise">


  .footer.special.enterprise {
    background-color: blue;
  }


That, too, yes.


I would use ".xed-footer" for reusable footer bearing the x caracteristic. And #main-footer for the stuff that stick at the bottom of most of my pages with unique caracteristics.

Way more self describing. No team member will ask which one is reusable and which one is not.


> I would still use .footer instead of #footer

Why?


I think the preference against ids is covered over point #2 about specificity. id styles will always override class styles, so when you're trying to apply a class-based style guide to an element that's already been styled with an id, you end up having to use !important which just creates a similar specificity problem for someone else down the line.

Of course, you can still do this if you want to. To quote Chris Rock, "you can drive a car with your feet if you want to." But if you work on a large code base that lots of developers have touched, and lots of future developers will touch, you run into these issues all the time. And the bugs that come about can be tough to spot and to fix.


If it's been styled with an id then it's already specially called out in the CSS.

Either remove that, or add the id to the selector with the style.


I agree with other poster.

For me it's a matter of doing things the same way so when I need to make an update to the code in a year it's intuitive.

"Be kind to your future self" is my motto.


Never understood why people prefer verbose and repetitive BEM classes over custom properties and appropriate CSS selectors.

  <div class="my-block my-block__my-element my-block__my-element--my-modifier">
becomes

  <div my-block="my-element my-modifier">
This solves for specificity, and uses built-in CSS features instead of a "manual" workaround.


This isn't a realistic example of how you should use BEM, you would never have a block, element, and modifier in one class. The "block" class would be used in a div that wraps the elements:

    <div class="block">
        <div class="block__item">
            I am an item
        </div>
        <div class="block__item block__item--danger">
            I am a dangerous item
        </div>
    </div>
Your simplification relies on an HTML hack and can potentially be more confusing when modifier names start colliding.


Yuck. I would follow the advise in this blog post [1].

https://www.smashingmagazine.com/2013/08/semantic-css-with-i...


Because "my-block" is not a valid attribute for div. You are breaking one language in your attempt to fix your problem in another language.


This argument doesn't stop a myriad of widely used JavaScript frameworks that rely on custom attributes. Besides, if you really care about validity, you can use

  <div data-my-block="my-element my-modifier">
It's still shorter, more readable and avoids repetitions. The difference becomes even more pronounced as the complexity of your styling goes up.


My argument about the attribute is not invalid because they are doing it the wrong way. Custom attributes for HTML should make use of the data attribute, as you point out. One could use data attributes in such a way, I have, but in the past it was something to avoid due to performance issues.

To be fair, I don't know the latest performance figures on attribute selection.


>My argument about the attribute is not invalid because they are doing it the wrong way.

The problem with this argument is that just a few years ago everything ReactJS does now was the wrong way, but for some reason today, it's the best way. So which is it?

It seems to me, that unless it's broken, or goes against an explicit rule from the browser/code designers of html/css etc... it's totally valid. And if it doesn't "feel correct", then maybe it's a trend waiting to happen. <sigh>inline javascript styles</sigh>


What was ReactJS doing a few years ago that was wrong then but correct now? Since I don't know what that is, did the spec change during that time?

As far as I know right now, custom attributes goes against the html standard.


>What was ReactJS doing a few years ago that was wrong then but correct now?

Inline styles for one... created with javascript no less. This was totally verboten not long ago. But then became a "best practice" only because React started doing it.


I disagree, inline styles is never a "best practice" no matter what the reason or who does it. It happens from time-to-time due to necessity, but that doesn't make it best practice. In this case, React is simply doing it wrong.


I'm a huge fan of 1 & 2, so I end up using CSS with only class names.

This helped me deliver maintainable and reliable stylesheets that other devs like.

Most importantly using only class names you will gain :

1. Your HTML / CSS is easier to maintain.

2. Is faster to develop.

3. Is faster to refactor.

4. Is more portable.

5. Is faster for the browser.

I even wrote a blog post about it [1].

http://www.drinchev.com/blog/css-with-only-class-names/


This might be right up your alley -- http://tachyons.io/ I also use a similar approach and thus love functional CSS :)


ID is faster than CLASS for the browser, especially when selecting by ID in Javascript.


But your HTML is uglier.


So? The only people looking at your html classes are you and your team. Bots don't process css, and most people don't look at html.


The same people looking and working on the CSS are the same people looking and working on the HTML. HTML full of long complex class names is a bit harder to grok.

I actually prefer nice semantic HTML but I admit that's not always possible.


> HTML full of long complex class names is a bit harder to grok.

I wouldn't recommend long and complex names either, but with something like tachyons, they're not long or complex, there are simply long lists of orthogonal classes.


The advice to use CSS variables to handle Z-index confusion is a good first step, but IME that's only the right way to handle global z-indexes like modal lightboxes and menus. For local z-indexes, you should also know how and when to create a new stacking context with position: relative.

This is the go-to article I send to newbies struggling with z-index. https://hackernoon.com/my-approach-to-using-z-index-eca67feb...


CSS Flexbox and CSS Grid allows one to reorder elements to avoid Z-index problems as well.


Using CSS-in-JS to enforce component-local CSS (and also allow easy dynamic updating of styles, by making a “getStyles” type function) is the best thing to happen to styling for a long time in my opinion. Recently I’ve been using the “styled components” pattern (using the Emotion library) and despite being initially sceptical, have found it really nice to work with.

So much more logical to write and maintain than plain CSS for a site of any reasonable complexity. You can still apply global styles where they make sense (e.g. styling all body text) and making use of JavaScript patterns for reusing common chunks of styling feels much more robust than the CSS equivalent.

As someone who can do CSS but doesn’t do so that often, I can confirm that it’s getting better with things like Flexbox and Grid, but it is still full of maddening quirks! I do have a lot of respect for people who are CSS experts.


As someone just dipping my toes into some Preact, I’m still a but confused about the styled components pattern. If you already have, say, a menu component in an es6 class, with its own methods and helpers and render func - how do you convert that to a styled component. All of the examples I’ve found just spin up new buttons pre-wrapped in Styled, etc

That’s my only real sticking point here.


I've heard about BEM many times and been forced to use it on a lot of projects. It seems to be reasonably commonplace I was hoping for some smaller tips so here's one I use very often.

Vertical height of text comes up a lot in CSS. It seems many people do not make liberal enough use of the line-height property. Line height is a magic bullet when you need some text to take up the correct amount of space.

With it, and your element styled to inline-block, of float left, or however you are using it. You are able to modify the font size later on without having any effect on the element's surroundings. It's also automatically centered vertically and you can change it without much effort.

Not enough people using line-height.


In my opinion, most CSS bad bits are a byproduct of bad use, not a problem of the language(?) itself.

SASS, BAM, OOCSS, etc are all good practices. You can/will abuse those as well without proper understanding and planning.


> In my opinion, most CSS bad bits are a byproduct of bad use, not a problem of the language(?) itself.

I've seen far too many bad languages come and go to believe that anymore. People used to say that about PHP and VB6 too.

PHP eventually stopped with the "only bad programmers use me badly" and grew up, and VB6 died. A win in both cases.

CSS could be far better; and bad practices won't disappear until doing it the right way is easier than doing it the wrong way.


The ability for good practices is already there, just too many people would rather complain about their bad practices to bother learning the good practices and blame the language.


-it is not possible to decrease scope

-tooling is hard e.g. to detect unused styles

-scope problems are a pain to debug

-some constructs are awkward (e.g. tooltips with :before and positioning styles)

-vertical text behaves unexpected wrt box model

-variables are suboptimal

There are probably a lot more.


1. I require more of an explanation as to what you mean by decrease scope. I could interpret that in different ways.

2. Sure, I understand the discipline necessary to prevent that is difficult in a team setting. I would say that likely at reaching that point something went wrong before then. That seems a tooling problem, not a language problem. How many languages provide features out-of-the-box that assist with discovering unused code without some form of third-party exploring that space?

3. In what way? What scope problems? I can think of several bad practices that lead to scope problems. I can think of examples of two people following two different best practices creating such problems.

4. I know it's not exactly a fair thing to say, but I don't have those issues with the example you provide. I'm sure there's plenty of examples of showing how to do it.

5. Flex. But, granted, old practices didn't handle vertical issues well because originally HTML wasn't intended for that.

6. In what way? Do you mean variables from a pre-processor or CSS custom properties?

I'm sure there are more, just like almost all languages have their quirks and issues that make it difficult to address if not understood. Do you have any other examples that we could discuss? Are there any specific use cases where you are having difficulties that I might be able to help out with?


If the language were better, they would have learned the good practices while they learned the language, and they wouldn't even be able to express bad practices without extra effort.


I'm surprised nobody mentioned using the Shadow DOM yet. That provides you with a very good means of scoping your CSS; e.g: within custom elements. Just look at Polymer.


For z-indexes, we're using a slightly an approach that I find a bit clearer:

  $some-element-z-index: 1 + max(
    $other-element-z-index,
    $should-be-below-z-index
  );
This way the relationship between elements that should be below or above is more explicit.

In my head, it works a bit like a spreadsheet. You update the z-index value of an element somewhere below, and all the z-indexes that depend on it update their value too.


I tend to write CSS for projects by hand without a pre-processor, borrowing from previous projects only when called for.

One of the things I've been doing recently that helps debugging a lot is to group the attributes within a css class into three, separated by a line.

1) Things that control where the item shows up.

2) Things that control the overall appearance of the item, like size and background.

3) Things that control appearance of things within the item, like font color.


That sounds a lot like the 'concentric order'. Can sort like that automatically: https://github.com/Siilwyn/css-declaration-sorter/blob/maste...


There is a different and IMO better way to solve the global scope problem in CSS. Adapted from the Paul Irish method of executing JS you can use data attributes to conditionally write CSS. For example a new user controller would output the controller and action names as data attributes on the body. I then have a separate css file under `assets/users/new.scss` which only contains css for that page. Your Sass code looks something like:

  [data-controller="user_controller"][data-action="new"] {
    .header {
      background-color: blue;
    }
  }
This method keeps you organized and completely removes the biggest problem most people have with CSS.


If we're going that way, you might as well include that particular file only on that page.


I would rather have one single request for a large static asset, than multiple small requests for per page based css. In my experience CSS files typically fall in the range 50-100KB. I'd rather not have to pay the perf penalty every time I load a new page considering the typical file size.


For what its worth, this is no longer the case with HTTP/2, which is up and coming for most sites (I hope). I imagine in a few years time this will be gone with the wind (hopefully).

see https://docs.google.com/presentation/d/1r7QXGYOLCh4fcUq0jDdD...

and

https://medium.com/@asyncmax/the-right-way-to-bundle-your-as...


I have been writing a lot of CSS (well SCSS) lately and this seems like a good time as any (though I admit somewhat off topic) about a question I have regarding the newer Combination & Multiple selectors https://developer.mozilla.org/en-US/docs/Learn/CSS/Introduct... and Attribute Selectors https://developer.mozilla.org/en-US/docs/Learn/CSS/Introduct...

This stems from the fact that I have inherited the task of re-writing a very large (at least for one person, I feel) task of re-writing an internal framework that is really gotten too burdensome to add anything to. I have been contemplating instead of trying to get crazy with a ton of different selectors where you end up with a pattern like this:

``` .selector .selector1 li, .selector .selector1 li a { some-style: some-value; } ```

Which I find A little crazy compared to something like this:

``` [class*="selector selector1] { some-style: some value; } ```

or my person favorite:

``` ul > li > a { color: blue; } ```

While these examples are I think very simplistic (I don't wanna junk up the page with tons of stuff) I've met alot of resistance to this idea, and splunking other frameworks for inspiration (Shout out to https://bulma.io ! I like their work, its really wonderful FYI.) I don't see alot of this.

While the resistance I've met from others who have some input on this project (and rightly so, they're also part of our stellar in house design team) seem to resist this idea, but haven't articulated why.

I was wondering if it comes down to: is there actually an issue with using these heavily vs some of the older semantics or, which I feel is quite possible, people have done things for so long one way its hard to see another way?

While its seemingly less verbose sometimes (not always) I feel like the new selectors give you a way to combat specificity problems by controlling when context around your classes is better than having ton of different classes and nesting those over and over.

Am i missing something?


Generally you would want to avoid descendant and child selectors. With rules like

  ul > li > a

  .selector .selector1 li a
The system will check ALL anchor tags and move left until it has completely matched the rule. This makes the above selectors extremely expensive (perfomance-wise) and can cause slow page-loads. Tag selectors and universal selectors are generally a bad idea for this same reason.

And using inheritance to select elements indirectly is actually better for performance than directly selecting the inheriting elements. For example, if you want to set typography for an entire page, instead of selecting all p and h1 tags, just select the body tag.

Here's a link to a more in-depth explanation of all of the above with examples:

http://mdn.beonex.com/en/CSS/Writing_Efficient_CSS.html


The good news is all modern browsers use a Bloom Filter to quickly skip over elements that wouldn't match the descendant or child selector relationship.

You could probably construct situations with very deep selector relationships and thousands of matching elements where the ancestor walking adds up but the other costs of computing style often end up being more important than the selector matching in many scenarios. Not that you shouldn't aim for simpler selectors of course.

(Usually the problems with expensive selectors come from side effects of dynamic changes to the document. ex. Some selectors will make the browser recompute hundreds of elements when only changing something small because the browser isn't tracking that relationship in a precise way.)


Hmm so what’s consensus then? Avoid these types of selectors when at all possible or no?


> Often there’s an argument to use tags to create a default set of styles. For most sites, it’s usually a good idea. However, if you’re just overriding those styles pretty much everywhere, I’d say don’t bother. Put them in generic utility classes (e.g. .paragraph, .heading-1, etc) and use them as you need.

Please don't. Tags have semantics for important reasons. Even if you're removing one of those by overriding the default styles, the semantics of tags are still used e.g. for screenreaders. It's not a mistake that HTML 5 added a ton of new semantic tags like <article>, <header>, <footer>, <aside> and <nav>.


I think the argument is against adding rules to tags to create a default set of styles, not against using semantic tags throughout the page.

If my understanding is correct, the argument is to use

  <style>
    .my-article {
      background-color: fuchsia;
    }
  </style>
  <article class="my-article">...</article>
rather than

  <style>
    article {
      background-color: fuchsia;
    }
  </style>
  <article>...</article>


One bad thing about CSS is cascading. Too bad that's the main thing. Some styles like colors and fonts move like a plague into every nook and cranny, all children elements get infected. Others like border get applied only onto the targeted element. Heavily nested selectors is another one, good luck overriding a style on a bootstrap element, their selectors strictly follow html nesting levels. You want to override a td style by a adding a class, you mean .table > tbody > tr > td.yourclass. Ugh. Sass only helps you write even more convoluted CSS if you don't know what you are doing, it's like C and C++.


>One bad thing about CSS is cascading.

This is an odd statement, considering that the C is CSS is "cascading". Maybe it's a perspective issue, because I really enjoy the cascading part of CSS. Don't you think it's better that we _don't_ have to set a color for each element/child element individually?


I know C in CSS is cascading, that doesn't make it a good feature. I think it's one of the big reasons that the web is slow and bloated. CSS is needlessly complex, no wonder it takes herculean efforts from browser vendors to keep up with the exploding complexities [1].

[1]https://hacks.mozilla.org/2017/08/inside-a-super-fast-css-en...


One reason for the cascading is to reduce bloat. If the CSS is bloated because of cascading and/or needlessly complex then the CSS and/or design is wrong, not the cascading.


I don't think the web is slow or bloated, only individual websites are slow or bloated. CSS is absolutely brilliant, and from what I have read, Javascript is the main culprit for badly performing websites.

I don't think a solid argument can be made that because the CSS rendering engine is complicated that it's not performant. Chrome documentation says it's possible to target 60fps with CSS/JS animations.[0]

[0] https://developers.google.com/web/fundamentals/performance/r...


Just like WASM allows us to implement new languages as alternative to JavaScript, could it one day become practical to implement an alternative to CSS?

EDIT: Perhaps by implementing the whole browser in WASM? Would that even make sense?


CSS Grid really helped me understand/wrangle z-index and stacking contexts. For example, within a grid you can use grid-row/grid-column to position an overlay over a grid item. The z-index will be scoped to that stacking context.

Modular CSS I think is a huge step forward - I totally agree that global scope is killer. As much as people love to hate on CSS-in-JS, I enjoy using styled-components a lot. I've noticed since using it I've been composing CSS instead of inheriting or overriding styles.


I think tooling is coming a long way to help with these - take for instance BEM. CSS modules is a great way to avoid needing BEM, as the bundler is handling the uniqueness of the classname for you (during minification etc.).

This is just the nature of web development - almost every tech in the stack is flawed, but tools and best practices make some sanity out of the chaos.


Best workaround for all the problems of the class discussed in the article: stop trying to be pixel-perfect.


Add another class to make your element more specific. You can have many classes in one element! Then you never have to use !important again.

  .rabbit.drivingACar.onIce.withRocketBoosters  {
    color: pink; /* pretty specific */
  }


Shadow dom and proper scoping (whichever popular method you chose for that) is a god send. I really dislike BEM though, we have files that have more classnames than content and tags combined :D


Just wondering how much more complains and valid critique against css is still required to get real alternative.

https://ishoudinireadyyet.com


I hope never enough, CSS is a fantastic language. Also, houdini won't replace CSS, it's actually the opening up of the CSS engine:

https://developers.google.com/web/updates/2016/05/houdini


I agree since most of the complaints and critiques of the language that I've seen are from people who don't appear to know how to code it correctly. Especially the complaints along the lines of "this is how it works in language X, it doesn't work that way in CSS therefore CSS sucks!" and other similar notions.


Safari is so bad.


Bad bits? More like code correctly, use already existing CSS features to your advantage, and use common sense when naming things. Then the so-called "bad bits" tend not to happen.


I'd add one thing: avoid multiple classes on a single element; use mixins to avoid duplication. I tend to do so even for classes that have some toggle state, i.e. .some-class-active.


does this have a performance benefit or are you recommending it for the code clarity?


It'll increase your parse and network transfer time (gzip might help there though) in exchange for reduced selector matching and style computation time. How much that matters probably depends on your content, how big the document is, how much CSS you have and how many classes you're using.

If you're talking about the difference of:

.a { ... } .b { ... } .ab { ... }

<div class="a b"></div> <div class="ab"></div>

It's probably not going to matter a lot. It's two map lookups vs one, and some associated overhead. Probably better to optimize elsewhere. :)


Best workaround: Quit front end web development. If that’s not an option, tough, you’ve got to use CSS.

Instead of quitting front-end dev, you might also consider using https://www.styled-components.com/

Styled-components solves all of the issues the author highlights in his writeup.

Bonus: styled-components works both on web and on React Native! So you don't have to throw out all your stuff to participate in the post-browser future...


>If you told any back-end developer that they had to use a programming language that gave all variables global scope, made every object’s internal state visible, let any other developer override their code, they’d probably resign on the spot

Isn't that the case with Javascript?


Nope. A variable is only global if you are in non-strict mode and leave off a `var` on the declaration, or explicitly assign to the global scope (aka window in the browser).

Object internal state is generally true, if you're using prototypal objects. Use function closures when you need to internalize something.

Speaking of which, anything hidden via closure is truly hidden and can't be overridden. Anything public can be overridden, excepting objects frozen via the ES5 spec's Object.freeze method.

I generally enjoy most aspects of JS, and generally detest working with CSS, in large part because I delegate interacting with many browser APIs to JS libraries, whereas there's no escaping the awfulness that is years of backwards compatibility with incompatible vendor specs and CSS implementations.

I suspect I'll be happier once CSS Grids are universally supported (properly) among all of the browsers I need to target, and use postcss for the rest.


yeah, so those developers resigned, got old and died, and now we're doing it anyway.


Use CSS Modules imo.


Keep going!

    z-index: 2147483647;


//[FIXME] Workaround for the component in IE

z-index: 2147483648 !important;


Stop using CSS and go with modular SCSS


>Stop using CSS...

Maybe I am stupid here, but doesn't SCSS just render out to CSS?


Yes, there's nothing that SCSS outputs that cannot be done in CSS.


For me the best thing about scss is the ability to nest selectors. This makes your code a lot easier to read and more organized. Of course having functions, mixins, extends is also nice.

Saying scss is pointless because it outputs regular css is the same as saying that es6 is pointless because it can be represented as regular es5.


>...es6 is pointless because it can be represented as regular es5.

Let's be reasonable, that's more like comparing CSS 2 to CSS 3. :P

Everything I've read and discussed with others in the industry, SCSS seems to be useful for far large projects with many designers and programmers stepping over eachother. I work for a smaller company, and we build very clean CSS, and would not benefit at all from SCSS.

Recently a friend at another medium sized company switched to SCSS "because". Seriously, it was one designer that liked one feature from some library that required some build tool that required SCSS... So they all have to learn SCSS now. No other reason.


The world really doesn't need another "What to Avoid with CSS" list.

This list also assumes the use of a CSS pre-processor.


I enjoyed reading it. I liked that fact that it wasn't a huge list, just 6 points. Well described, good examples, and well structured with the "Best workaround" sections. To me it felt big enough to hold real value but small enough to easily consume. It's something I'd probably share with juniors on my team.


Maybe you've learned everything there is to know about CSS, but I haven't, and I prefer to learn from the mistakes of others rather than my own (not that I don't make plenty of my own).


Well, I liked it. I had never heard of BEM before, either, so I'll definitely take a look at that. What gets me about CSS is that, in spite of having used it now for about 20 years, I still don't have an intuitive feel for it. With everything else I work with, I start out with an experimental approach: if I change this, I see this, if I change that, I see this other thing; after usually a few weeks of experimentation, I develop an intuition for it so that I can usually predict what it's going to do before I have to see it do it (admittedly it took more than a few weeks to get to that point with Lisp and assembler). CSS, though, just seems to deny intuition; even after reading the O'Reilly "CSS: The Definitive Guide" book, I don't have the faintest clue what my CSS is going to do until I try it out.


Hear, hear! Working exclusively in scss, maintaining orderliness and decent discipline, and having - like you - been at it for close on twenty years, I still keep a constant wary eye on my output screen, I still get regular surprises there, I still rely on the browser dev-tools, and I sorely miss the 3d representations they used to have, at least in Firefox.

I have learned to simply accept css for what it is: An unholy legacy kludge we have to live with. Just don't let's speculate on the millions and millions of wasted man-hours over the years.


>I had never heard of BEM before...

Welcome to css-tricks.com [0], where you will learn all the current trends. I am a regular reader for things just like this. Where you just want to know what's new and where things are going. Plus they have an amazing stockpile of CSS examples.

Second only to Mozilla Developer Network. [1]

[0] https://css-tricks.com/

[1] https://developer.mozilla.org/


It's getting better as of late. I would spend some time reading up on flexbox and css grid if you haven't.




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

Search: