Difference between "[class='something']" vs '.something' - html

What is the difference between selecting in the DOM with these formats '.selector' and '[class="selector"]'?
I would expect the same result using either of both, but the element is not found when using the second variant. Why?
> document.querySelectorAll('[class="cropped-profile-image__picture"]')
NodeList []length: 0__proto__: NodeList
> document.querySelectorAll('.cropped-profile-image__picture')
NodeList(2) [div.cropped-profile-image__picture.cropped-profile-image__picture--type-cover, div.cropped-profile-image__picture.cropped-profile-image__picture--type-profile]

.selector matches any element which has any class selector. I.e. it will match class="selector foo".
[class="selector"] matches any element that has exactly the value "selector" in its class attribute. I.e. it will not match class="selector foo".

The difference being that .something selects all elements that have something class on them - even if they have other classes. While [class='something'] only selects those elements that have only one class 'something'.
In the snippet below, you can see that .something applies a red border to both boxes, while the [class='something'] selector applies a background color to only the first box.
div {
width: 100px;
height: 100px;
margin: 5px;
}
.something {
border: 2px solid red;
}
[class='something'] {
background-color: blue;
}
<div class="something"></div>
<div class="something else"></div>

When you use an attribute selector, you are attempting to match exactly the string that you pass. The class attribute would need to be cropped-profile-image__picture, nothing more, nothing less.
For example, the following <div> would match your first query selector:
<div class="cropped-profile-image__picture"></div>
But this one wouldn't:
<div class="cropped-profile-image__picture another-class"></div>
Because the class attribute doesn't exactly reflect what you have queried.
When you query a class using a period (querySelectorAll('.cropped-profile-image__picture')) you are using a DOM API that will return elements that have that class, whether they have more classes or not.

The selector only selects exact matches, but the elements also have the class
cropped-profile-image__picture--type-cover

Related

Use attribute selector for selecting by class instead of proper class selector

I'm just working on a email html template and I came across this:
*[class=width100pc] { width: 100% !important; }
I've never seen something like this before. Is there a reason of using this syntax for selecting by class instead of just using
.width100pc {width: 100% !important;}
I know that CSS is kind of limited in email clients, is it somehow related to it?
You would use *[class=width100pc] to style any element where width100pc is the only class.
*[class=width100pc] { color: red; }
<div class="width100pc">Hello</div>
<div class="width100pc another-class">world!</div>
A standard class selector will apply regardless of other classes.
.width100pc { color: red; }
<div class="width100pc">Hello</div>
<div class="width100pc another-class">world!</div>
The one reason that comes to my mind is when class selector is not supported in a specific environment where this code is used, but can be bypassed by using attribute selector.

Targeting a class when inside another class

I am creating a div that will have a default style but is also going to have various options for different styles depending on the content. My goal is to be able to have these styles take effect only when nested inside of the custom class name. Kind of hard to explain verbally so I'll give some code examples of what I mean:
This will be the html structure for the default view:
<div>
<div class="default"></div>
</div>
This will be the html structure for the custom view:
<div class="custom">
<div class="default"></div>
</div>
So basically I need to be able to write a class that will say "redefine these styles on default only when default is nested inside of custom"
Really just looking for confirmation on the syntax involved here.
My first thought is to write something like:
.custom .default {
declaration: attribute;
}
I'm just a little unsure of whether this will only target default when it's inside of custom or if this will globally redefine default, I can't live test it just yet because ftp transfer hasn't yet been set up for me on this server.
Thanks in advance for any clarity on this!
Yes, that's right. This will target any .default contained by a .custom (at any point in its ancestry) (fiddle):
.custom .default {
color: red;
}
See the descendant combinator and others.
And yes, it can override declarations specified by .default (fiddle):
.default {
color: green;
}
.custom .default {
color: red; /* overrides green */
}
Have a look at selector specificity.
So, canon's answer is enough... But, just for the clarity that you asked.
You can restrict your selector to target only a nested element, with two methods:
Descendant Selector: It's written with a white space and targets the child element at any nested level inside the parent:
MDN ref docs
.parent .child {
/*styles*/
}
Child Selector: It's written with a > charachter, and targets the child only if it is directly nested, an immediate child:
MDN ref docs
.parent > .child {
/*styles*/
}
You were right. And if you want to make sure to target only the direct descendants, you can do this:
.custom > .default {
declaration: attribute;
}
That would be helpful in case you had something like:
<div class="custom">
<div class="default">
<div class="default"></div>
</div>
</div>
CSS will look for an element that has a class of default which is encapsulated within a parent with the class custom, any child nodes which match this rule will have the styling applied to them, you can create as many different themes for the same element as you wish, so long as you change the class.
So your code:
.custom .default {
declaration: attribute;
}
Is perfectly correct.

Style first element with class

Is there a way to style only the first element with a specific class? The :first-child psuedo selector seems to only work on tags.
EDIT: Not all classes have the same parent element so :first-child isn't an option.
You may try like this:
<div>
<p class="blue">1st</p>
<div class="blue">2nd</div>
</div>
<div>
<div class="blue">3rd</p>
<div class="blue">4th</div>
</div>
So this will make only the first element as blue
Also check :first-child pseudo-class
The :first-child pseudo-class matches an element that is the first
child element of some other element.
.class-name:nth-of-type(1)
This should style what you want
JsFiddle example
This should work .classNamep:first-of-type
You need to double check your class name. A typo could happen.
See this fiddle. It shows you that :first-child works even with class selectors. :)
Code:
<span class="spana">first</span>
<span class="spana">second</span>
.spana:first-child {
background-color: #ddd;
}
Using the nth-child() pseudo class selector is a good approach, this is supported in all major browsers, including IE9+.
Here is the example HTML:
<div class="blue">Will be blue</div>
<div class="blue">Will not be blue</div>
<div class="blue">Will not be blue</div>
<div class="blue">Will not be blue</div>
And the CSS:
.blue:nth-child(1) {
color: blue;
}
This will select the first div of class name blue. Bare in mind that the first iteration is selected by passing 1 into the pseudo class, not 0 like arrays for example.
There are also other key features of the nth-child() pseudo class; as well as passing in numbers like I have shown previously, the pseudo class also supports key words such as even or odd like so.
//Applies styling to every even instance of the class .blue
.blue:nth-child(even) {
color: blue;
}
//Applies styling to every odd instance of the class .blue
.blue:nth-child(odd) {
color: blue;
}
This can also be taken further; a formula can be expressed as to exactly which elements the styling is to be applied to.
The formula is expressed an+b, where a is the frequency of the elements to select, and b is the offset. So the formula 3n+4 will apply styling to the fourth element, and every third element beyond that. (4, 7, 10, 13, 16, etc...). Below is an example of how this can be applied.
//Style every 6th instance of the class .blue, starting with the second element. (2, 8, 14, 20, 26).
.blue:nth-child(6n+2) {
color: blue;
}
If no offset is required then simply pass in the same formula as before, dropping the offset at the end; passing in 4n is an example of this.
I hope this helps, I feel that this pseudo class is very powerful, and equally under rated by a lot of people.
There is no first-of-class selector.
See BoltClock's answer (CSS3 selector :first-of-type with class name?)
There is a work around but it didn't work for me

How to reference a long class name with spaces in CSS?

I'm trying to style some Drupal output. In particular, I'm trying to reference a class with a super long name (that includes spaces). I'm unclear the syntax for this. Forgive me, I'm a CSS newbie. See:
<article id="node-38" class="node node-article node-teaser contextual-links-region node-even published with-comments node-teaser clearfix" about="/~actionin/node/38" typeof="sioc:Item foaf:Document">
<header>
<h2 property="dc:title" datatype="">National Nutrition Month: March 2012: “Get Your Plate in Shape”</h2>
I ultimately want to reference the H2 property. I was thinking it would be something like:
.node SOMETHING-HERE .header h2 { declaration; }
I cannot just reference the node, since it is used elsewhere for other purposes. I want to be specific and select only this class:
class="node node-article node-teaser contextual-links-region node-even published with-comments node-teaser clearfix"
Using dots (.) you can combine multiple class as a group
.node.node-article.node-teaser.contextual-links-region.node-even.published.with-comments.node-teaser.clearfix {
...
}
Maybe I'm not giving you the answer you need, but class names cannot contain spaces.
An element can have multiple classes, which allows you the combine multiple styling rules for different classes to apply to a single element.
If you have spaces in a class attribute, it creates an element with multiple classes, delimited by spaces.
For example, if you have an element like this
<div class="big red outlined"></div>
and you had CSS like this
.big {
width: 1000px;
height: 1000px;
}
.red {
color: red;
}
.outlined {
border: 1px solid black;
}
All three styles would be applied to the single div to make it big, red, and outlined.
In your case, it looks like you are trying to access a specific element, which is what the purpose of the id attribute is. Notice that the node has a unique id:
<article id="node-38">
You can access an element with a specific id in CSS by using the # selector, like this
#node-38 {
//style goes here
}
In your case, you probably want to do something like this:
#node-38 .header h2 {
//style goes here
}
Those spaces are effectively multiple classes on the one element, so your <article> tag has the "node" class, and the "node-article" class, and so on and so on.
So if you had:
.node { background-color: black; }
.node-article { color: white; }
Then the article would have a black background, and white text. Both would be applied.
Also remember you can reference tags, and ids, so to get to your H2 you could do:
article header h2 { .... }
or
#node-38 header h2 { .... }
And you don't necessarily need the "header" in there either, depending on what you want to achieve.
If you want to select all <h2>s that are descendants of <article> tags with the "node-article" class, then you can do this:
article.node-article h2
class="node node-article node-teaser contextual-links-region node-even published with-comments node-teaser clearfix"
Above line contains total 9 classes because of spaces between them. so, node is a single class, node-article is another class and so on. If you want to reference a class then you should write it like
.node{background-color:red;}
If you want to reference multiple classes at once and want to apply same styles then you can write like
.node, node-article, node-teaser{background-color:red;}
In that case three individual classes node node-article node-teaser will have the same style with background color red. Now if you have multiple elements with same class i.e. article then all article with same class will have same style. To apply a style to a unique element you can id instead of class like id="node-38" and you can apply style with CSS to this element like
article#node-38{background-color:red;}
to select/reference the h2 inside header with parent element article that has id="node-38" you can write
article#node-38 header h2{background-color:red;}
When you define an element with a class, including spaces actually denotes multiple classes.
That article actually has the following classes applied to it : node, node-article, node-teaser, contextual-links-region, node-even, published, with-comments, node-teaser, and clearfix.
You could use any of those classes when targeting the element. If I were referencing the H2 tag I would do something like
article#node-38 header h2{
This is a much more specific way to target than using all of those classes. it's shorter syntax, and more specific to the element you want to style.

Reuse classes in an id based css

I have a id based CSS file where I noticed I'm mostly repeating myself. What I'd like to do is specify that an item with an id follows a certain class + some other rules. For example: I'd like id id1 to have all the properties of class LinkButton applied as well as the value back-color: green. Is there a way to do this in the css file? Is there a better way to do what I'm looking at?
You can specify multiple selectors on a given set of properties, like this:
.LinkButton , #id1 { color: red; border: solid 1px blue; } /* Both get these */
#id1 { back-color: green; } /* Adding rules */
It can also override any of the properties if you need:
.LinkButton , #id1 { color: red; back-color: red; } /* Both get these */
#id1 { back-color: green; } /* Changing rules */
Or you give the element the class and ID:
<div id="id1" class="LinkButton ">
There's no need to work with ID based style sheets. Avoiding repetition is exactly what classes are there for. Why not use classes instead of IDs? They are much more flexible, and take away nothing. (You can still target speficic elements.)
You can combine multiple CSS classes wonderfully (except for IE6, whose interpretation of multiple classes is broken.)
<span class="info extrabig highlight"> Important hint </span>
if you have a particular element that needs really specific rules, then give it a class named after its ID:
<span id="really_special" class="id_really_special info extrabig highlight">
and define the unique properties of the element in the .id_really_special class.
IDs are there to access elements through the DOM imo. Styling should really be left to classes.