Let's say I have some deeply nested markup that I want to target with CSS. It could be anything, but for example:
<div>
<div id='someid'>
<span class='someclass'>
<a class='link' href='alink'>Go somewhere</a>
</span>
</div>
<div>
Is it acceptable to write a CSS rule targeting the <a> tag directly, like this?
a.link { font-size: large; }
Or is this considered non-standard that may fail in some browsers? Do I need to target each element in the chain like this?
div div span.someclass a.link { font-size: large; }
Both are completely acceptable to use and the answer depends on your specific solution. For instance if you have other areas where you are sharing common properties that are defined by that class you'd want to keep it as general as possible. If for instance you have a navigation and the links in that area share some common elements those could be defined by a.link
Then in your nested html, you might do something like
.someclass a.link {font-size:8px} to make that text smaller.
Here is an article that discusses how the specificity works: http://coding.smashingmagazine.com/2007/07/27/css-specificity-things-you-should-know/
Both are perfectly valid, and which one you use depends on what you want to do.
If you are creating a generic class that you want to be able to use throughout your entire site regardless of element and where the element is, you should only use .class. A good example for this is something like .icon which you may want to use on links, list items, headings etc. And you want to be able to use them everywhere.
If you're creating a class that is specific to/only works on one certain type element, it's best to use the element in the selector as well. An example of this would be a bullet list you want to display on one line, since this class requires the HTML to be a <ul> you should specify it in the CSS as well; ul.inline. This way you can use the "inline" class name for other elements as well, without the styling affecting both.
If you're only using the class in order to select the element but it shouldn't have any generic styling you should be specific. For example, you may want the first paragraph in your #blog-post element to be larger, then you should specify both #blog-post and the class; #blog-post p.first (note that these types of classes are rarely needed anymore thanks to advanced selectors like :first-of-type, h2 + p etc).
Saying that ".link is the best, a.link is second best and a long selector is bad" is just wrong. It all depends on the situation.
The more targeted you make your CSS the less flexible it becomes. It's your own trade off. If you are going to give the links a specific class like that I am pretty sure they'll be visually the same whether they appear inside this tree or outside of it so you can stick with your first example.
It's actually recommended to use a.link instead of the long, ugly second option, which can cause specificity and performance issues.
It's even better if you use just .link. That's the best option.
a.link is the best way to do it. If you want a certain a.link to be different from the rest, you'll need to add some weight to it.
a.link { ... } /* Global */
span.someclass a.link { ... } /* Finds all a.link within span.someclass */
Descendant selectors (line 2) aren't the most efficient way to add style to an element, so use them sparingly. Personally, I use them when I need to give special styles to a Global Class within a certain ID/Class.
Related
I'm building an app with many different components and I've run into an issue where styling from one component has overlapped with styling from another component. Other than giving each paragraph tag it's own class, is there anyway to prevent this? Say with a keyword or something?
Try to use as a specific selector as possible in your CSS file. It isn't just .class or #div. When you find a more specific selector you can always add !important after all your style.
It will have a higher importance level than everything else, but you can still change it from a different file if you use the same level.
This can be something like this:
.some-div > p {
font-size: 16px !important!
}
Please check this https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors for selectors.
I don't think there is any other way than giving unique class to every element.
Let me elaborate:
If you have used a web framework, say NextJs, you will see that it assign a unique class to every element to avoid class collision within page. And Styling IS one of them.
So yeah, Having unique classes IS necessary to avoid css collision, unless you don't go for an ID approach.
So, I was looking at a tut on youtube the other day, and this guy kept defining css rules with classes really weirdly, and I wondered if one of u guys could explain the necessity of it: here is the code:
ul.class li{
color:#fff
}
Why can't he just do:
.class{
color:#fff
}
Thank you for reading my question, I hope you understand what I am asking for.
Video: https://youtu.be/2wCpkOk2uCg
P.S - Sorry for the giganticly large title 😏
When you put the element before the class, CSS only applies the styles to the members of that class that are of that specific element.
For example, if you had .class applied to 3 headers and 3 paragraphs, writing p.class would only affect the paragraphs.
With ul.class you're saying "Apply this styles to all the ul's with this class. If you only use .class you're saying "Apply this styles to ANYTHING that has this class". It's very different. :)
I can think of at least two reasons to include the element name as well as the class:
Specificity, i.e., which CSS rule takes effect on a target element when multiple rules apply to to it. There is a specificity algorithm that determines which rule is applied when multiple rules are in competition. This awesome Specificity Calculator is a great tool to help you understand the algorithm. So, in short, including the element name and the class gives it additional weight.
Documentation in your CSS. I tend to include the element as well as the class, e.g. h1.customer-name, to self-document what type of element the rule is being applied to. When I see .customer-name without the element name, I am not totally confident in what type of HTML element it is. Doing this means I don't have to keep the HTML structure in my head or consult the HTML repeatedly while I work on CSS. But this is pretty dependent on one's approach to CSS as well as the tools used, so I'm not sure I would consider it a good idea across the board.
And one more, but not least important thing. If you adding the tag name before the class name (such as span.class{}), so you got more specific rule and it's have bigger priority (no matter in which order that rules writter in css file). For example, if you write two rules:
.class { color: red }
and
span.class { color: blue }
you will get a blue text as a result.
For example:
.main .box{
//rules
}
These rules will affect all box so long as they are inside of a tag of class main
Lets say I have about 100 rules on this page and all of them are only to be enforced if inside a tag of class main. Is there an easier way to enforce this or do I have to place .main in front of every rule in the .css? If there a way to declare this simply at the top of the .css?
You can try this....place the same prefix in front of each child class within .main, then use the class or ID attribute "begins with" selector
.main [class^="main-prefix"] {}
or for IDs
.main [id^="main-prefix"] {}
The attribute selector is saying that any element that has a class/ID that begins with - you can also place an asterisk in front of the bracket but it is not necessary:
.main *[id^="main-prefix"] {}
These selectors would apply to classes such as .main-prefix-box
The short answer is "no". In plain CSS, you will have to put .main in front of every rule in the file. The longer answer is "sort of". If you are using a pre-processor like LESS or SASS, you can do something like the following:
.main {
.box {
//rules
}
// rinse and repeat
}
That said, if this is the only thing you need a pre-processor for, it's likely to be overkill. In many cases, pre-processors can help make your code easier to maintain and write (such as with situations like your example). However, you should evaluate your own needs against the pros and cons to decide whether it makes sense in your case.
You have to put them in front of every rule in the .css.
You can look into css preprocessors like SASS or LESS to make your life easier for these things.
There isn't really an easy way to declare this for an entire file. You would have to use a preprocessor like SASS or LESS to do that. Which allow you to embed CSS selectors inside of other selectors. But it's either that or putting it in front of ever selector.
I firstly say that i don't know anything about how css rules are assigned to DOM elements by browser, so that my question is more around it, but i got wondering this in this particular situation I got into, so I use it for formalizing my curiosity:
I do have an HTML snippet like this:
<section>
<div>I'd like to be blue</div>
<div style="color:green">I am quite <p style="font-weight: bold">self confident</p> about my styles</div>
<p>I'd like to be biig</p>
</section>
The text's content of the divs tries to describe my requirements: The first div MUST be blue, the second one i don't care because I will probably use inherited properties or I will set through js or whatever.
The p should be bold,
So I want to assign styles to do that, and I do something like this:
section div {
color: blue;
}
section p {
font-weight: bold;
}
And that obviously works as expected. But, CSS has nice features to target more specific elements. So I could do, for doing the same thing:
section > div:first-child {
color: blue;
}
section > p {
font-weight: bold;
}
This will affect only elements that are direct children of the section, and only the first div of the set, so that i will have the same result, but selecting elements more specifically.
I wonder if this helps browsers assigning css rules to elements.
I think that at some level the browser check for each DOM element the css' rules that target it, and if it finds matches (a css class is actually targeting it), it checks for conflicts and performs overriding if needed.
Would excluding elements from that sets, by targeting them more specifically help the browser to assign style (increase performance or decrease) ?
If it increases, is it meaningful or it is so little that everyone ignores it ?
If it decreases, how much and why ?
Thanks for any advice.
According to this article from Mozilla Development Network, the more specific your selectors are, the better. So if you do not bother how many divs get colored blue, the general selector section div is better. The longer your selector chain is, the harder it is for the browser to find that element since it needs to match more things. The most performant option in this case would actually assigning a class named for example .blue to the div you want blue.
The element>element (direct child) selector is more performant than the element element (descendand) selector in the sandbox but will probably force you to write a longer selector chain if you wish to overwrite it at another point.
To answer your question, in your example (at least in a nutshell), the overall performance will probably decrease by a little (meaningless) bit since pseudo-elements like :first-child are the least performant selectors and you furtherly have a longer selector chain.
If you actually asked me which of those to use in a project with more than just six lines of css, I'd encourage you to use the first example aswell since it's much more easy to overwrite and reuse.
I read an article with some css file
#mainNav #toTop a {
float: right;
margin: 0 8px 0 0;
font-size: 40px;
}
Can someone explain why they have two # things in one css id type ? and how can I use it?
Thank you in advance
I don't know what you mean by a "CSS id type". So I'm just going to explain CSS in general, and we'll see if what this snippet is doing becomes clear.
In CSS you have selectors and property blocks. Your question is about a selector:
#mainNav #toTop a
Selectors are used to target (and on some other platforms to query) HTML (and sometimes XML) elements. This particular rule is using three simple selectors - two id selectors and a tag name selector - put together with two descendant combinators.
That means the selector will target (and the rule block accompanying it will affect) any anchor element (<a>) which is the descendant of any element with id=toTop which in turn is the descendant of any element with id=mainNav.
Since id elements are supposed to be unique, it might seem silly to have two of them in one selector. You can do it if you want to though, and sometimes you'll need to: we haven't spoken about selector specificity.
Specificity defines which rules take precedence over other rules. For example, if two elements both seem to target the same element:
form .label { color: blue; }
#contact-us .label { color: green; }
/* what color is the label? */
... then which rule takes precedence? To figure that out we calculate the specificity. I won't explain the math.
So, let's suppose you have a CSS stylesheet in your project which you can't change - it comes from a 3rd party vendor or something, and it looks like this:
#toTop a { /*...*/ }
If you needed to change the styling of the elements affected by that rule, what would you do?
You could (and probably would) define a new rule with greater specificity. One of the ways you can do that is by adding another id selector to your rule:
#mainNav #toTop a { /*...*/ }
But realistically you could just as easily add any other selector:
div#toTop a { /*...*/ }
Realistically whether it's necessary or not depends on what you're trying to do, what other rules it's interacting with, and what kind of HTML you're dealing with.
Here's another thing to consider: CSS stylesheets are meant to be re-used. What if that element should behave differently if it is in a different place in the document? What if the id="toTop" is sometimes inside the id="mainNav" element on some pages, and in a different place (let's say in the id="footer" element) on others? What if it moves, depending on client-side JavaScript? Then you might want to define CSS like this:
#mainNav #toTop a { /*...*/ }
#footer #toTop a { /*...*/ }
... so ultimately again, why a developer would choose to do this really depends on the CSS, JavaScript and HTML they are working with. It's definitely unusual, but it's not unnecessary nor bad practice.
ID must always be unique. However it is valid to use more than one id to make styles more specific.
In your example you are looking for an element with id #toTop inside #mainNav.
This is a perfectly valid CSS rule. It is very specific. The motivation for this use may have to do with how the page layout is designed and/or how JavaScript handlers interact with the DOM.
This is an example of poor CSS. The selector hierarchy in your example is redundant and unnecessary. It says select all a elements that are descendants of the element with the ID of toTop that is a descendant of the element with the ID of mainNav. So it assumes a basic structure like this:
<div id="mainNav">
<div id="toTop">
link
</div>
</div>
However, as IDs must be unique, only this is needed to target the same elements:
#toTop a
#mainNav #toTop a is using the Descendant Combinator to specify an element a descendant of an element with id toTop descendant of an element with id mainNav.
As said by other answers, this rule seems to be overly specific, because IDs must be uniques and then #toTop a should do the trick.
The real reason behind the choice of declaring this rule is:
Assuming that in a website you have one or more shared CSS (read:
you don't have an different CSS for every page), this rule means:
in a page where a is descendant of #toTop, but #toTop is descendant of an #mainNav element too, then apply this rule;
in a page where a is descendant of #toTop, but #toTop is NOT descendant of an #mainNav element, then DO NOT apply this rule;
because #toTop could be an reusable element that could be declared in different places (one-per-page, of course), for example inside the #mainNav in a page, and inside the #sideNav in another page, with a desired potentially different behavior and look-and-feel.