Could Grouping HTML Classes Make Them More Readable?

You can have multiple classes on an HTML element:

<div class="module p-2"></div>

Nothing incorrect or invalid there at all. It has two classes. In CSS, both of these will apply:

.module { }
.p-2 { }
const div = document.querySelector("div");
console.log(div.classList.contains("module")); // true
console.log(div.classList.contains("p-3")); // false

But what about grouping them? All we have here is a space-separated string. Maybe that’s fine. But maybe we can make things more clear!

Years ago, Harry Roberts talked about grouping them. He wrapped groups of classes in square brackets:

<div class="[ foo foo--bar ] [ baz baz--foo ]">

The example class names above are totally abstract just to demonstrate the grouping. Imagine they are like primary names and variations as one group, then utility classes as another group:

<header class="[ site-header site-header-large ] [ mb-10 p-15 ]">

Those square brackets? Meaningless. Those are there to visually represent the groups to us developers. Technically, they are also classes, so if some sadist wrote .[ {}, it would do stuff in your CSS. But that’s so unlikely that, hopefully, the clarity from the groups outweighs it and is more helpful.

That example above groups the primary name and a variation in one group and some example utility classes in another group.

I’m not necessarily recommending that approach. They are simply groups of classes that you might have.

Here’s the same style of grouping, with different groups:

<button class="[ link-button ] [ font-base text-xs color-primary ] [ js-trigger ]" type="button" hidden>

That example has a single primary name, utility classes with different naming styles, and a third group for JavaScript specific selectors.

Harry wound up shunning this approach a few years ago, saying that the look of it was just too weird for the variety of people and teams he worked with. It caused enough confusion that the benefits of grouped classes weren’t worth it. He suggested line breaks instead:

<div class="media media--large testimonial testimonial--main"> 

That seems similarly clear to me. The line breaks in HTML are totally fine. Plus, the browser will have no trouble with that and JSX is generally written with lots of line breaks in HTML anyway because of how much extra stuff is plopped onto elements in there, like event handlers and props.

Perhaps we combine the ideas of line breaks as separators and identified groups… with emojis!

See the Pen
Grouping Classes
by Chris Coyier (@chriscoyier)
on CodePen.

Weird, but fun. Emojis are totally valid there. Like the square brackets, they could also do things if someone wrote a class name for them, but that’s generally unlikely and something for a team to talk about.

Another thing I’ve seen used is data-* attributes for groups instead of classes, like…

<div class="primary-name" data-js="js-hook-1 js-hook-2" data-utilities="padding-large"
>

You can still select and style based on attributes in both CSS and JavaScript, so it’s functional, though slightly less convenient because of the awkward selectors like [data-js="js-hook-1"] and lack of convenient APIs like classList.

How about you? Do you have any other clever ideas for class name groups?

The post Could Grouping HTML Classes Make Them More Readable? appeared first on CSS-Tricks.

CSS Selectors are Conditional Statements

.foo { }

Programmatically, is:

if (element has a class name of "foo") { }

Descendent selectors are && logic and commas are ||. It just gets more complicated from there, with things like combinators and pseudo selectors. Just look at all the ways styles can cascade.

Jeremy Keith:

If you find you can’t select something in the CSS, that’s a sign that you probably need to add another class name to the HTML. The complexity is confined to the markup in order to keep the CSS more straightforward, modular, and maintainable.

Direct Link to ArticlePermalink

The post CSS Selectors are Conditional Statements appeared first on CSS-Tricks.

One Invalid Pseudo Selector Equals an Entire Ignored Selector

Perhaps you know this one: if any part of a selector is invalid, it invalidates the whole selector. For example:

div, span::butt { background: red;
}

Even though div is a perfectly valid selector, span:butt is not, thus the entire selector is invalidated — neither divs nor span::butt elements on the page will have a red background.

Normally that’s not a terribly huge problem. It may even be even useful, depending on the situation. But there are plenty of situations where it has kind of been a pain in the, uh, :butt.

Here’s a classic:

::selection { background: lightblue;
}

For a long time, Firefox didn’t understand that selector, and required a vendor prefix (::-moz-selection) to get the same effect. (This is no longer the case in Firefox 62+, but you take the point.)

In other words, this wasn’t possible:

/* would break for everyone */
::selection, ::-moz-selection { background: lightblue;
}

That would break for browsers that understood ::selection and break for Firefox that only understood ::-moz-selection. It made it ripe territory for a preprocessor @mixin, that’s for sure.

That was annoying enough that browsers have apparently fixed it. In a conversation with Estelle Weyl, I learned that this is being changed. She wrote in the MDN docs:

Generally, if there is an invalid pseudo-element or pseudo-class within in a chain or group of selectors, the whole selector list is invalid. If a pseudo-element (but not pseudo-class) has a -webkit- prefix, As of Firefox 63, Blink, Webkit and Gecko browsers assume it is valid, not invalidating the selector list.

This isn’t for any selector; it’s specifically for pseudo-elements. That is, double colons (::).

Here’s a test:

See the Pen Ignored Invalid Selecotrs??? by Chris Coyier (@chriscoyier) on CodePen.

I’d call that a positive change.

The post One Invalid Pseudo Selector Equals an Entire Ignored Selector appeared first on CSS-Tricks.

Selectors That Depend on Layout

“Why the heck don’t we have ::first-column?”

I heard someone ask that the other day and it’s a valid question. I’d even take that question further by asking about ::nth-column() or whatever else relates to CSS columns. We have stuff like ::first-letter and ::first-line. Why not others?

There are many notable things missing from the “nth” crowd. Seven years ago, I wrote “A Call for ::nth-everything” and it included clear use cases like, perhaps, selecting the first two lines of a paragraph.

I don’t know all the technical details of it all, but I know there are some fairly decent reasons why we don’t have all of these in CSS. Part of it is the difficulty of getting it specced (e.g. words and characters get tricky across written languages) and part of it is the difficulty of implementing them. What I just found out is that there is a FAQ document that explains!

So, why don’t we have ::first-column? Because it’s a “selector that depends on layout”:

This falls into a class of problems that unlikely to be solvable in CSS: selectors in general, and pseudo classes in particular, cannot depend on layout, because otherwise they could be used to modify layout in a way that made them no longer match, which would modify the layout back to where it was, so they match again, and we get stuck in an infinite loop of contradictions.

For a simple example:

:stuck { position: static; }

Now what?

Some of the changes web developers might want to apply with a :stuck pseudo class may be safe and not trigger such loops, but selectors are a generic mechanism, and would enable this kind of contradictions.

So even though many of the problem people are trying to address using such pseudo classes are legitimate, selectors are unlikely to be the answer.

What we’ve got are infinite loops that are basically the problem (but read the FAQ — it goes into great detail about the nuance of it). In a related way, the same reason we don’t have element queries in CSS.

It’s a little tricky to think about because even stuff like ::first-line are riddled with paradoxes. Say you use it to increase the font-size. That means fewer characters fit on the line, so the characters that originally matched are now pushed down and don’t match anymore. Seems a bit loopy, but that’s been sorted out. Plus, classics like :hover potentially causing jitter. The document talks about these things in clear terms. It’s not all cut and dry!

The whole FAQ is a fascinating read and covers much more than this situation.

Direct Link to Article — Permalink

The post Selectors That Depend on Layout appeared first on CSS-Tricks.

“Stop Using CSS Selectors for Non-CSS”

I saw Nicole Dominguez tweet this the other day:

I wasn’t at this conference, so I have very little context. Normally, I’d consider it a sin to weigh in on a subject brought up by looking at two out-of-context slides, but I’m only weighing in out of interest and to continue the conversation.

The idea seems to be that if you need to select an element in the DOM with JavaScript, don’t use the same selector as you would in CSS.

So if you have…

<article class="article">
</article>

…and you need to apply an event listener to that article for some reason, then don’t use…

$(".article")

(or querySelector or whatever, I assume.)

Instead, apply an attribute intended just for the JavaScript to target, like…

<article class="article" data-hoverable>
</article>

…and target that like…

$("[data-hoverable]")

The idea is that you can separate jobs. The class has the job of styling, and the data attribute has the job of JavaScripting. Both can change without affecting each other.

Seems reasonable to me.

Also seems like there is plenty to talk about here. Performance, I suppose, but that’s probably the least-interesting thing since selectors are generally pretty damn fast these days. We could continue the conversation by talking about:

  • What naming convention?
  • Should you be naming events?
  • What if it needs to be selected for different reasons multiple times?
  • Can you or should you use IDs?
  • Is it worth avoiding DOM selection at all if you can?
  • What other nuances are part of this discussion?

I saw Michael Scharnagl had some thoughts on his own usage of ID’s, classes, and data-attributes that could help frame things a bit.


“Stop Using CSS Selectors for Non-CSS” is a post from CSS-Tricks