Use css syntax or custom class - css

Bit of a noob so need some real world advice.
I've just been reading an article written by mozilla regarding the use of css selectors.
Basically, they're saying don't use complex selector trees, for instance:
.class-a .class-b > .class-c is better expressed as custom-class-abc
Obviously they would because the second option is going to be better for the performance of the browser, but if this is the best solution, then it sort of renders a lot of css basics redundant.
I have a UL containing LI's that contain A's. My first A needs to be treated differently, so I use the following syntax:
#footer li:first-child a {}
If I was to follow Mozillas best practice, this would be:
#footer a.first or #footer .first (after adding a class to the first A element)
There is enough to learn as it is, so would appreciate some advice on how this all works in the real world.

Your selector is just fine. Having not read the article you mention I would guess they mean to avoid something like
html body div.wrapper div.navigation ul.nav li:first-child a.item { }
and just do
.nav li:first-child a.item
This article gives a little bit more on why fewer selectors are better for performance. Of course there are extremes of everything and mozilla should recommend how to make things as fast as possible but selectors are already extremely fast so in most cases it makes no difference.
On a related note reading up on specificity in css may also help you determine how much you actually need to select. http://coding.smashingmagazine.com/2007/07/27/css-specificity-things-you-should-know/

I think the article may be out of date to cater for the dumber browsers, but most up to date browsers understand :first-child now. Your example
#footer li:first-child a {}
is how I rock. ie8 doesn't understand :last-child take note.

Related

CSS: Best practice for selecting deeply nested elements [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I frequently need to address generic elements inside some specific sections of a page. I find this approach most easy to understand in terms of what any rule is affecting:
.shop > .products > .product > .description > .warning {
color: red;
}
But I often see this:
.shopProductsProductDesc > .warning {
color: red;
}
Does it really matter which approach is taken?
It really depends on the problem you are trying to solve.
The selector .shop > .products > .product > .description > .warning to my understanding would be used for two cases:
You have multiple warning elements but you only want to select the elements inside your description and there are other selectors used for warning that you don't want to overwrite.
You need to overwrite a previous selector that is less specific. Ex. .shop > .products > .product > .description .warning
The other selector .shopProductsProductDesc > .warning is less specific than the first one but assuming the container of .warning has those two classes .description.shopProductsProductDesc then the outcome would be the same as the first one.
CSS is all about specificity, if your selector is more specific than the last one used the properties would change. This is why you have to be careful if you are using specific selectors because your last option to alter the properties would be to use !important.
I hope this helps to clear things out.
After trying a few different styles, I think that personal preference (or a set standard if you have collaborators) is really the way to go. I prefer the second version, but the first one is also quite legible.
If you consider efficiency of what the browser has to do under the hood to render CSS styles, BEM-style for example, is usually the ultimate winner as it is the most lightweight for the browser. I use BEM for some layout/common elements.
In real life unless you are doing something seriously wrong, modern browsers and devices make this difference of CSS parsing and rendering somewhat negligible. But that is if you code everything well.
I've worked with spaghetti CSS codebases that could take minutes to render all SCSS (it was a huge codebase, but a few files were big bottlenecks).
It matters because of specificity. The first style rule will always override the second, regardless of where they both appear in the stylesheet, because it is more specific (basically it has more class selectors in it).
That said, the first rule is a nightmare from a maintainability perspective, for a number of reasons:
It makes code incredibly hard to read and understand
It's harder to override (as we have seen).
If you change the structure of the HTML, it will break
You can only reuse it if you mirror the structure of the HTML exactly.
It's also bad from a performance perspective. When browsers are matching an element to a style rule they read each selector right-to-left and keep going till they either find a match or can exclude the rule. Therefore, the more simple the selector is, the faster a match can be determined. If a selector consists of just a single class name, the browser can match the element with the style rule more quickly than if it has to search upwards in the DOM tree.
The second rule is better, but optimal would be something like the following:
.shopProductsProductDesc--warning {
color: red;
}
This solves all the problems above, and it's long enough that there's unlikely to be name clashes elsewhere, (though obviously not impossible).
In general, nesting selectors in CSS is bad practise, in my opinion, and the best CSS methodologies are those that have ways of avoiding this, e.g. BEM, CSS-in-JS.
According to my own experience, the second option is often best, not for direct technical reasons (in fine, it will perform the same), but rather for UX consistency and code maintenance.
The first option produce an "heavy" selector, which will be harder to override. It can be wanted, but it is often the sign of an overall messy CSS, because if everything is overconstraint, it is less easily reusable/extensible.
From my understanding of CSS and frontend reusable components, you would always only need two levels.
The style of your warning component (no size, no margin, size depends on where you will display it, and margin is position, only internal design here):
.warning {
//Your design here
font-size: 1.5rem;
font-weight: bold;
color: orange;
}
And the positionining and variants inside containers:
.container > .warning {
//This is an example.
position: absolute;
right: 0;
border: solid 1px red;
}
Having long CSS selectors will make things more complex, hard to follow for your teammates, and hard to override because you will probably need a longer CSS selector, and it never ends. Plus, you will get an heavier bundle at the end.
If you want an efficient UX, the UI shouldn't be that different everywhere, so you should not need to have that many variants of the same component. Otherwise, maybe you need multiple different components, but you certainly want a simple and efficient UX, and that often goes with not so much visual concepts, so you must avoid tons of variants.

CSS grouping :hover & :active

When I want to define css selector with :hover and :active I have to do:
#mainPage #content div.group:hover, #mainPage #content div.group:active {}
As one can see it contians repeated #mainPage #content div.group and can get messy. Is there a way to group it somehow like:
#mainPage #content div.group:hover:active {}
In pure CSS there is not much of a better way to handle both more succinctly without adding a class or ids.
You could consider a CSS pre-compiler (like LESS or SASS/SCSS).
In LESS or SCSS:
#mainPage #content div.group {
&:hover, &:active {
color: red;
}
}
I suggest add ID for the element has class group and write below code will reduce the effort:
#idname.group:hover, #idname.group:active{}
Is there a reason why you're using #mainPage #content before div.group?
Generally, it's not necessary to add that much 'specificity' to your selectors - it's better to instead, have unique classes. So make sure that the class .group is only used for elements that you want to have the same styles.
If you do that, you should be able to style those elements just using
.group { styles here}
You might run into an issue now where if you try to override any of the styles you set like #mainPage #content, those will be more specific and so in effect 'stronger' than styles where you don't use the full list of parents. If possible, change all your styles not to include the parent elements - this is also worthwhile in case you ever want to move an object to a different part of the html!
It's also, in general, advisable not to use id's (#name) to attach css styles - if possible, just use classes. Unless you're doing javascript, you shouldn't have much need for id's.
Obviously there exceptions to the above, and for all I know you may have a perfectly good reason for doing things the way you have - in which case SASS (as suggested in a few other answers) is a good solution for you.
If not useful for you, I hope at least this answer might be useful for someone who might come along later - I've noticed that a lot of people newer to css don't realize how specificity of selectors works and end up making their styles a lot more complicated than necessary as a result! :)
Old question, but this should be relevant for somebody who needs this.
Pseudo-class released by the end of 2020
You can use :is() pseudo-class like so :
#mainPage #content div.group:is(:hover, :active) {
}
Here is a little snippet to picture it :
a:is(:hover, :focus) {
color: red;
outline: #5bc8ea dotted 4px;
outline-offset: 4px;
font-weight: 600;
}
Hover/Focus me
More informations about :is() pseudo class here: https://developer.mozilla.org/en-US/docs/Web/CSS/:is and here: https://css-tricks.com/almanac/selectors/i/is/.
Works with most of the popular browsers (incompatible with IE, Opera and Safari < 14) https://caniuse.com/css-matches-pseudo.
It surely is more often used to select elements than pseudo-classes like :hover or :focus but it will do the trick as I can't see any other solution for now.
Why you use #mainPage #content? #content should be enough to find the div your looking for without the #mainPage.
Also id's are only allowed to be used once and not in multiple places like classes are. Id's are usually reserved for script assignments and not CSS. I would do
#content .group:hover{}
#content .group:active{}
if i understood correctly, you want a group of elements to act a certain way? manipulate the parent class then.
.parent-class:hover {
.child-class {
…desired styles go here
}
}

Using css universal selector (*) for clearing the flow

This works, but actually I've never come across it earlier. Does it have some "weak spots"?
div.floated { float: left; }
div.floated+* { clear: both; }
Though I did not notice any "side effect".
You can use it at your will, although according to MDN, you should take into account that universal selector is the most expensive CSS selector in terms of webpage performance.
Universal CSS Selector Performance
Here some problems I see:
"floated" is not a semantic class name.
This will clear adjacent elements after divs with the "floated" class, but not anything that is floated by other means.
In most designs I work with, I don't want to clear adjacent elements. Now I'll have to write more CSS to undo this.
I think I don't understand the value of this.

CSS inheritance issue

I have a old css line taking precedence over my new <img> ID CSS how can I over-ride this?
I'm looking to change the width of an image within greybar, and cannot change the image width with a new ID.
Here's my code:
#greybar img {
width: 75px;
float: left;
margin: 10px;
}
#rpmimage {
width: 125px;
}
You need to look up CSS Specificity. In short, different selectors get a different score.
An ID is worth 100, a Class is worth 10, and a tag selector is worth 1.
That means that #greybar img is worth 101, whereas #rpmimage is worth 100. Hence, the first one 'wins'.
Many people recommend not using IDs for CSS, and not to over-qualify selectors where needed to help.
In you case, try #rpmimage img instead, or rethink what you are doing with this new knowledge!
There are a variety of 'bad things' to do, including using inline styles (like you'll remember you did that next time you have a problem!), or using !important. Thing with !important is that it takes priority over everything which means next time you have this issue you have nowhere to go.
http://coding.smashingmagazine.com/2007/07/27/css-specificity-things-you-should-know/ is a great article that has some good practice in it, and is worth reading for everyone really!
For a nice tool to help understand more complex selectors, try http://specificity.keegan.st/ - this lets you test things like #id:after p > img to see what specificity they have.
I think you should be able to do an in-line style, at least as a quick and dirty trick.
For example:
<img style="width:75px;" ... >

Using a general purpose selector as a mixin in LESS CSS

I know about mixins and parametric mixins. What we are looking for is a way to make any general purpose selectors in CSS / LESS into a mixin.
Eg in Twitter BootStrap, we have here
.navbar .nav > li {
float: left;
}
If I have to use it in a class say .mynavbar I want to be able to do this
INPUT->
.mynavbar {
.navbar .nav >li;
}
OUTPUT->
.mynavbar {
float:left;
}
Now I know this can't be done with the current version of LESS as the compiler flags a parser error. I wanted someone to help me out on changing the source code of less.js a little so that this is workable.
I've managed to reach the source code for the mixin parser. I've tried changing the RegExp there, but it interferes with other parts of the parser. I know we have to make only a few changes because, instead of just accepting .mixin and #mixin we have to accept any mixin like tags / attribute selectors like input[type=text].
It is currently needed for the development of a UI framework that uses Bootstrap. Unfortunately many places in bootstrap are littered with direct tag selectors instead of ids and classes.
This is possible since version 1.4.0 (2013-06-05) of LESS that include the extend feature. Based on the original example
.navbar .nav > li {
float: left;
}
.mynavbar:extend(.navbar .nav > li) {}
compiles to
.navbar .nav > li,
.mynavbar {
float: left;
}
Documentation here and discussion & example use for the original question here
EDIT: Added Code Sample
First off, I would strongly discourage doing such things. Instead, try to use the power of CSS and build your HTML such that the bootstrap rules apply, for example. Anyway, since you asked for it, here is the solution.
The problem is not the complexity of the selector, or the child rule, but the tag name selector part (i. e. the li). So, what we have to fix is the mixin parser only matching classes and ids. I guess we would not want to tamper with the first class or id test, since that is probably needed to distinguish mixins from normal CSS rules (although the tests run fine with that check commented out). (Actually, there is a parser preference in action, and the only thing tried after mixins are comments and directives, so we can safely remove that check as well). However, we can easily allow tag names in later parts of the mixin selector by adding a question mark after [#.] in the matching regular expression. So
while (e = $(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) {
– i. e. line 825 – becomes
while (e = $(/^[#.]?(?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) {
The test cases still run through fine, afterwards, but subtle breakage my occur, so be cautious.
Edit: There is a GitHub Issue for the same problem. Apparently the less folks rather want the mixin feature to be more narrow and function-like, instead of allowing a more flexible … well … mixing in of rules. With regard to the CSS output, that's probably reasonable.

Resources