Benefits of [class="classname"] over .classname for emails - css

Why would class selection by attribute [class="classname"] be used in place of selection by class .classname? Are there any benefits for this when considering cross email-client compatible emails?
Edit: I am fully aware of how each selector works, however, I am trying to figure out if there is a reason selection by attribute would be used over selection by class for compatibility reasons (specifically in the case of a class attribute consisting of one class) due to the issues with css and email clients. This question arose after reviewing a responsive email template that explicitly used class selection by attribute over selction by class.
e.g.
.red-text { color: red }
[class="red-text"] { color: red }
<td class="red-text">This text is red</td>

These are not equivalent.
[class="a"] will match <div class="a">, but not <div class="a b">.
.a will match both <div class="a"> and <div class="a b">.
For example:
div.green {
color: #0f0;
}
div[class="red"] {
color: #f00
}
<div class="green"> green </div>
<div class="green bold"> green with other classes </div>
--
<div class="red"> red </div>
<div class="red bold"> red with other classes <-- I'm broken </div>

.classname will match this element, but [class="classname"] will not.
<div class="foo classname other">
hello world
</div>

Related

Precedence of "concatenated classes" vs "separated classes" in CSS selectors [duplicate]

This question already has answers here:
Specificity of inherited CSS properties
(4 answers)
Closed 3 months ago.
Can someone please point me to the CSS precedence rules regarding "concatenated classes" vs "separated classes"?
Also, what are the correct terms for "concatenated classes" vs "separated classes" (I suspect that's why I can't find the documentation I'm looking for.)
For example, in the CSS below, .row .second (with a space) appears to take precedence over .row.second (no space), even though they both match 2 class attributes.
.row {
width: 150px;
background-color: lightgray;
margin: 15px;
}
section {
margin-left: 15px;
}
.row .second {
color: purple;
}
.row.second {
color: orange;
}
When applied to the HTML below, the CSS above produces this result:
Why is "Stuff 2b" in purple instead of orange? (In other words, why does .row .second take precedence over .row.second in this case?)
<div id='outerBox'>
<div class="row">
<div class="title">
Row 1 Title
</div>
<section>
Stuff 1a
</section>
<section class='second'>
Stuff 1b
</section>
<section>
Stuff 1c
</section>
</div>
<div class="row second">
<div class="title">
Row 2 Title
</div>
<section>
Stuff 2a
</section>
<section class='second'>
Stuff 2b
</section>
<section>
Stuff 2c
</section>
</div>
<div class="row">
<div class="title">
Row 3 Title
</div>
<section>
Stuff 3a
</section>
<section class='second'>
Stuff 3b
</section>
<section>
Stuff 3c
</section>
</div>
</div>
(I'm applying the CSS above to the HTML below in JSFiddle in Chrome on MacOS.)
separated classes is using for Childs in css.
Example :
.row .red # Means red Childs in Row
{
color:red;
}
<tr class="row">
<td class="red">
<p>Hey!</p> ### Color of this P will be red.
</td>
</tr>
The color of the classnamed as "red" elements in ".row" will be red.
But concatenated classes using for like "with".
Lem me show a example;
.row.red # Means class="row red"
{
color:red;
}
<tr class="row">
<td class="red">
<p>Hey!</p> # Color of this P will not be red.
</td>
</tr>
<tr class="row red">
<td class="">
<p>Hey!</p> # But this one will be red.
</td>
</tr>
While most commonly used, classes have nothing to do with Object Orientation. This means that there is no OO mechanism to 'concatenate/separate' anything. It's pure a syntax for creating different kinds of CSS selectors. I always consider CSS definitions as an eleborate list of if-statements.
without space, .row.second: all .row elements that are also .second
with space, .row .second: all .row elements that have .second child elements in their list of child elements. Any nesting deep.
This also means that there is no specific precedence at play in your case.
You either select any second row element or any second child element of any row element.
I get the feeling that your confusion originates from the difference in notation in CSS and HTML tags:
<tag class="row second"> with space is not equal to.row .second { ... } also with space, but equal .row.second { ... } without space.
It literally means a <tag> that is both a .row and a .second.
With space in CSS litterally means select all parent tags that are .row and select all .second child tags of those parents.
Update
I forgot to mention (like #TemaniAfif did) that color is inherited from the parent, I assumed it to be known by OP.
snippet showing the various possibilities:
div>* {
background-color: lightgray;
margin: 15px;
}
/* the default for all */
.row, .default1 { color: purple }
.second, .default2 { color: orange }
/* exceptions in special cases */
.row.second, .exception1 { color: green }
.row .second, .exception2 { color: red }
<p><b>Legend:</b> explanation per parent class used and (rule that applies)</p>
<h3>no parent class</h3>
<div>
<div>no class, will be document default</div>
<div class="row">row, will be purple (default1)</div>
<div class="second">second, will be orange (default2)</div>
<div class="row second">row second, will be green (exception1)</div>
</div>
<h3>.row parent</h3>
<div class="row">
<div>no class, will be purple from parent (default1)</div>
<div class="row">row, will be purple, like parent (default1)</div>
<div class="second">second, will be red, because child of row (exception2)</div>
<div class="row second">row second, will be red, overrides parent (exception2)</div>
</div>
<h3>.second parent</h3>
<div class="second">
<div>no class, will be orange from parent (default2)</div>
<div class="row">row, will be purple, overrides parent (default1)</div>
<div class="second">second, will be orange, like parent (default2)</div>
<div class="row second">row second, will be green, overrides parent (exception1)</div>
</div>
<h3>.row .second parent</h3>
<div class="row second">
<div>no class, will be green from parent (exception1)</div>
<div class="row">row, will be purple, overrides parent (default1)</div>
<div class="second">second, will be red, because child of row (exception2)</div>
<div class="row second">row second, will be red, overrides parent (exception2)</div>
</div>

CSS selector, Match element that doesn't match given selector

I'm trying to match element that dose not match given selector using css.
Given the markup below, I'm trying to select only the first ".color"
<div uid="unique-id-1">
<div> <div class="color"></div> </div>
<div uid="unique-id-2">
<div class="color"></div>
</div>
</div>
I tried [uid="unique-id-1"] .color:not([uid="unique-id-1"] [uid] .color) which did not work obviously, but I think it will help to understand what I am looking for.
Thanks in advance!
If you're only going to apply the selector to this limited combination of elements (i.e. there aren't any other .colors in the page that could potentially be affected by this), then
[uid="unique-id-1"] > div:not([uid]) > .color
Do consider renaming the attribute to data-uid if your application allows, so as to make it clearer that this is an app-specific and non-standard uid attribute.
That seems simple:
[uid="unique-id-1"]>:first-child .color {
color: red;
}
<div uid="unique-id-1">
<div>
<div class="color">A</div>
</div>
<div uid="unique-id-2">
<div class="color">B</div>
</div>
</div>
That being said, uid as an attribute name makes your HTML invalid, so you should rename that to data-uid:
[data-uid="unique-id-1"]>:first-child .color {
color: red;
}
<div data-uid="unique-id-1">
<div>
<div class="color">A</div>
</div>
<div data-uid="unique-id-2">
<div class="color">B</div>
</div>
</div>

css not select the first class between other container

css doesn't select the first class
:not(:first) doesn't work because .callout is wrapped by other container
.callout:not(:first) {
color: red;
}
<div class="d-flex">
<div class="flex-fill">
<div class="callout">
Text A
</div>
</div>
<div class="flex-fill">
<div class="callout">
Text B - only this set color red
</div>
</div>
</div>
Select the .callout element whose parent is not the :first-child of its parent element
.flex-fill:not(:first-child) .callout {
color: red
}
Or just revert the logic and target the :last-child
.flex-fill:last-child .callout {
color: red
}
Or target the .callout inside the second parent element, no matter how many .flex-fill siblings you have
.flex-fill:nth-child(2) .callout {
color: red
}
Codepen example
Anyway, I don't recommend to use this kind of selectors or to rely on a specific markup structure because this approach can easily cause maintainability problems as the code grows and, if possible, I'd suggest to place instead a specific class for this purpose on the right element.

Checking if data attribute is set at parent div css / less and using it for the child divs as well

I have div tag for which a data-type attribute is associated. I want to apply different styles depending on data-type is set or no.
<div data-type="type1">Hello, World!</div>
Can I check if this attribute data-type is set or no in css/less ? This question is solved with this.
But, if I apply this data-type attribute only to the parent div, can I use this attribute for all the child div tags as well.
For instance,
<div data-type=`type1`>
<div id="newDiv"> </div>
</div>
In my CSS, I want to apply different styles for #newDiv depending on whatever type (data-type) is set to its parent. I don't want to specify the data-type attribute to the child div as well. How do we do this in CSS ?
You can use :not([data-type]) to select any element that does not have the attribute data-type set regardless of the values used.
Basic working example:
div:not([data-type]) {
color: red;
}
<div data-type="type1">Hello, World!</div>
<div>Hello, World!</div>
Alternatively, you can do the opposite and use [data-type] to select anything with the data-type attribute set regardless of the value
Working example:
div[data-type] {
color: red;
}
<div data-type="type1">Hello, World!</div>
<div>Hello, World!</div>
If you want to target a child div whose parent div has the data-type attribute set the you can use something like this:
div[data-type]>h1 {
color: red;
}
<div data-type="type1">Hello, World!
<h1> How are you?!</h1>
</div>
<hr>
<div>Hello, World!
<h1> How are you?!</h1>
</div>
This also can be reveresed based on your selector preference to target the child elements of parent elements which do not have the data-type attribute set.
div:not([data-type])>h1 {
color: red;
}
<div data-type="type1">Hello, World!
<h1> How are you?!</h1>
</div>
<hr>
<div>Hello, World!
<h1> How are you?!</h1>
</div>
If you have more complex structures you can make use of the wildcard * selector to build selectors that match very broad patterns. The letters represent the depth of the tree on which the element resides with aaa being a direct child and bbb being a grandchild...etc
Basic Example:
[data-type] * h1,
[data-type] h1 {
color: red;
}
<div data-type="type1">
<h1> aaa</h1>
</div>
<hr>
<div>
<h1> aaa</h1>
</div>
<hr>
<div id="test" data-type="type1">
<div>
<h1> bbb</h1>
<div>
<h1> ccc</h1>
</div>
</div>
<h1 class="wow"> aaa</h1>
<div>
<h1 class="wow"> bbb</h1>
</div>
</div>
<hr>
<div id="test">
<h1 class="wow"> aaa</h1>
<div>
<div>
<h1> ddd</h1>
</div>
<h1 class="wow"> ccc</h1>
</div>
</div>
If you find a pattern in your data-type value, yes, you can:
/* 1. Attribute value starts with "type" */
div[data-type^="type"] {
/* Styles */
}
/* 2. Attribute value contains "type" */
div[data-type*="type"] {
/* Styles */
}
Works for: type1, typex, typeaskdasd, etc...
Works for: abctypexyz, typexyz, etc...

How can I style .class-0, .class-1, .class-2 with a common selector?

I want to style the following CSS classes; is there any short styling technique for this?
.test-0 { }
.test-2 { }
.test-3 { }
/* etc. */
I am looking for something like:
.test-%d% { }
I want to dynamically create many test-* classes with different numbers and common styles.
Update
here is my actual situation
<input type="button" value="click" class="button_class" />
<h1 class="ui-widget-header">Question - 1 </h1>
<div class="ui-widget-content">
<div id="form_container-0">
<div class="placeholder">Add your form fields here</div>
<div style="clear: both;"></div>
</div>
</div>
When user click the above button then same structure will clone and append to the end of the form
so the form will be as
<h1 class="ui-widget-header">Question - 1 </h1>
<div class="ui-widget-content">
<div id="form_container-0">
<div class="placeholder">Add your form fields here</div>
</div>
<div id="form_container-1">
<div class="placeholder">Add your form fields here</div>
</div>
</div>
the css class form_container-[%d] will be created dynamically by jquery.
so i want to add style to this class.
also it would be great if you share optimised code for cloning the structure with
different ID.
Please do let me know if you still have doubt.
thanks
You can use an attribute selector.
div[class*='test-'] {...}
I think #Ed W have the right solution BUT I have an extra idea while is not straight forward is shorter than what you have. And will help to make different testing that is waht I think you want... fiddel http://jsfiddle.net/ncubica/2sj9W/
css
.test-1,
.test-2,
.test-3,
.test-4,
.test-5{
color:#F60;
display:block;
}
.test-5{
color:blue
}
html
<span class="test-1">One</span>
<span class="test-2">Two</span>
<span class="test-3">Three</span>
<span class="test-4">Four</span>
<span class="test-5">Five</span>
span five will be in blue color... so you can override the class you want to test and play with it.
Also you can use selectors like
HTML
<div>
<span>I'm pink</span>
<span>I'm pink</span>
<span>I'm pink</span>
<span>I'm pink</span>
<span class="test-1">I'm red</span>
</div>
CSS
div > span{
color:pink;
display:block;
}
div > span.test-1{
color:red;
}
and the last span will be red. I hope this help.
My two cents...

Resources