LESS - what is the purpose of "&" AFTER a nested selector [duplicate] - css

This question already has answers here:
Ampersand (parent selector) inside nested selectors [duplicate]
(3 answers)
Closed 8 years ago.
Less
.list a{
.landscape&{
height: 100%;
}
}
Outputs
.landscape.list a {
height: 100%;
}
Which means "all a tags whose parents have both .landscape and .list"
Less
.list a{
&.landscape{
height: 100%;
}
}
Outputs
.list a.landscape {
height: 100%;
}
Which means "all a tags which have class 'landscape' and whose parents have .list"
And that makes sense. But if I remove the "a" tag from those selectors, the '&' only changes the concatenation order of .list and .landscape.
What's the point ? When should I use &.class and when should I use class.& ?

The & in Less denotes the parent selector. So wherever you put the &, it replaces it with the parent selector in the CSS, if you have a space before it.
If not, i.e., no space is given before the &, it becomes the child and appends the selector with its parent like in your case.
References:
Less CSS Secrets-of-the-Ampersand
Parent Selector

The article "LESS CSS: Secrets of the Ampersand" details the difference well. I'll highlight the key uses:
Attach a class to an existing selector
Change state based on parent classes
Filter a nested selector to only match certain elements
Avoid repetition when selecting repeated elements
Simplify combinatorial explosions
The latter is my favorite. I've used it to handle some crazy IE issues. Check this out:
/**
* Add a top border to paragraphs,
* but remove that border when a preceding paragraph already has one.
*/
p {
border-top: 1px solid gray;
& + & {
border-top: 0;
}
}
I think if you can wrap your mind around what this usage of & does, all the other uses become obvious.

Related

what does &::before mean in scss [duplicate]

This question already has answers here:
What does '&.' in '&.sub-title' indicates in scss?
(1 answer)
What does the & mean in an scss selector?
(1 answer)
What does an "&" before a pseudo element in CSS mean?
(4 answers)
Closed 4 years ago.
I came across some stying in my scss file which looks like this:
:host {
&::before {
content: '';
display: block;
width: 100%;
height: $channel-border-w;
background: $color-border-divider-bg;
}
}
does this mean to style the element before my host?
From MDN docs,
In CSS, ::before creates a pseudo-element that is the first child of the selected element. It is often used to add cosmetic content to an element with the content property. It is inline by default.
The & before it indicates that it is adding this pseudo selector to the selector it is nested under, which is your host element.
The snippet you posted could be translated to:
:host::before {
... your styles here ...
}
& adds something selected to parent selector.
::before creates a pseudo-element as child of parent selector.
i let you the full doc here:
http://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector
https://developer.mozilla.org/en-US/docs/Web/CSS/::before
https://css-tricks.com/the-sass-ampersand/

CSS3 style an element depending on the state of an input checkbox

What is the meaning of '~' in this example? I saw this example from this tutorial. http://css-tricks.com/the-checkbox-hack/
I know it can be used to style an element completely differently depending on the state of that checkbox. However, I can't find any CSS documentation that explains '~'?
input[type=checkbox] {
position: absolute;
top: -9999px;
left: -9999px;
/* For mobile, it's typically better to position checkbox on top of clickable
area and turn opacity to 0 instead. */
}
/* Default State */
div {
background: green;
width: 400px;
height: 100px;
line-height: 100px;
color: white;
text-align: center;
}
/* Toggled State */
input[type=checkbox]:checked ~ div {
background: red;
}
It's a selector for sibling elements. The one you have there will find all of the 'div' siblings of a checked checkbox within the same parent, but only ones that follow the checkbox in the dom. 'Div' siblings preceding the checkbox will not be included.
Awesome selectors reference, including the tilde:
http://learn.shayhowe.com/advanced-html-css/complex-selectors
It is a general sibling combinator and similar to Adjacent sibling combinator (+). The difference is that the second selector does NOT have to immediately follow the first one means It will select all elements that is preceded by the former selector.
http://www.w3.org/TR/selectors/#general-sibling-combinators
8.3.2. General sibling combinator
The general sibling combinator is made of the "tilde" (U+007E, ~) character that separates two sequences of simple selectors. The elements represented by the two sequences share the same parent in the document tree and the element represented by the first sequence precedes (not necessarily immediately) the element represented by the second one.
Example:
h1 ~ pre
represents a pre element following an h1. It is a correct and valid, but partial, description of:
<h1>Definition of the function a</h1>
<p>Function a(x) has to be applied to all figures in the table.</p>
<pre>function a(x) = 12x/13.5</pre>

CSS style for parent instead of child?

I am using jquery to insert html I get from the server into a div. Based on the div contents i'd like to adjust the syle of the container. I wrote up a simple html test. How do I tell css to apply this site when it has X child? After googling I tried :has and :contains with neither working. I don't want to keep my styles in JS as css makes more sense.
Demo: http://jsfiddle.net/wd9fk/
html
<div id="a"><div id="b">B</div></div>
<div id="a"><div id="c">C</div></div>
css
#a { height: 400px; border: 1px solid red; }
#b { height: 200px; }
#a :has #b { height: 300px; border: 1px solid blue; }
You simply cannot traverse up the DOM in CSS. You will need to use JavaScript.
Here is an article explaining why: http://snook.ca/archives/html_and_css/css-parent-selectors
Long story short, it's due to the way CSS is read by the browser, and by introducing it, it would increase the performance hit by a factor of ten (at least!), because it would need to read every single node multiple times to see whether or not it fits the profile.
It's a nice thought, but it's simply not viable.
There is no parent selector for CSS yet, there are plans and it is being discussed though. In CSS Selectors level 4, a subject selector has been proposed, which would let you refer to elements this way:
ol! > li:only-child
Which then reads: “an ol element that contains a single li element” (this syntax is a proposal though), and would let you style the parent ol element.
If this proposal succeeds, subject selectors would be available in the next version of CSS selectors.
For now, Javascript is the way to go, until the subject selector becomes a standard.
You cannot traverse up the DOM to get the parent selector of current matching elements.
But you can do it with jQuery quite easy like this:
$('#Default a span.active').closest('.vehicle_details').css('background-color','#444');
Fiddle Demo
#a > #b { height: 300px; border: 1px solid blue; }
Not sure if this is what you wanted, but give it a try.
Regards.

CSS selector issue for multiple elements

I thought I had my CSS down fairly well but I cannot seem to figure out why this problem occurs. I must be doing something wrong.
So if I want to select multiple elements that are children to a div I could write:
#mydiv > input, label{
}
Am I correct? I thought this to be true until I realized that other inputs and labels in my site were inheriting these CSS properties even though they were not in the div called #mydiv. To fix the issue I had to use:
#mydiv > input, #mydiv > label {
}
But I am pretty sure that this is not the quickest way to do so. I tried checking the Selector Page on W3.org but they do not give an example for my situation.
What am I doing wrong?
Am I correct?
No. The grouping selector (comma) has the lowest precedence, so you cannot use it to select multiple elements that are children of a div using this selector:
#mydiv > input, label
The most concise selector is the one that you found on your own:
#mydiv > input, #mydiv > label
You can DRY things up a bit using nested rules in LESS or Sass, though that does introduce a dependency in your code and/or build process.
Your second snippet is the simplest way to do it with pure CSS. The comma , separates isolated CSS selectors, so that's why you needed to begin each with #mydiv for both selectors.
You could use something like LESS, which would allow nested rules. Non-germane example:
#header {
h1 {
font-size: 26px;
font-weight: bold;
}
p { font-size: 12px;
a { text-decoration: none;
&:hover { border-width: 1px }
}
}
}
But you're probably better off with pure CSS.
Your second method is good
#mydiv > input, #mydiv > label {
}
If you wanted to somehow do this without using multiple selectors separated by a comma, you could use a class name for both your input and label elements
.your-class-name {
}
or if for some reason input and label were the only two types of child elements for #mydiv, then you could use the universal selector like this:
#mydiv > * {
}

CSS precedence

My webpage contains:
<link href="/Content/Site.css" rel="stylesheet" type="text/css" />
<style type="text/css">
td {
padding-left:10px;
}
</style>
The referenced stylesheet contains:
.rightColumn * {margin: 0; padding: 0;}
I have a table in the rightcolumn ID where I want the cells to have a little padding. However, the referenced stylesheet is taking precedence over the inline styling. I see this visually and also via Firebug. If I turn off the padding:0 instruction in Firebug, the padding-left takes effect.
How can I get the padding-left to work?
Most of the answers are correct in saying that this is a specificity problem but are incorrect or incomplete in explaining the specificity rules.
Basically in your case .rightColoumn * is "more specific" than td and so that rule wins even though it comes earlier.
The CSS 2.1 rules are located here. These rules are:
count 1 if the declaration is from is a 'style' attribute rather than a rule with a selector, 0 otherwise (= a) (In HTML, values of an element's "style" attribute are style sheet rules. These rules have no selectors, so a=1, b=0, c=0, and d=0.)
count the number of ID attributes in the selector (= b)
count the number of other attributes and pseudo-classes in the selector (= c)
count the number of element names and pseudo-elements in the selector (= d)
Concatenating the four numbers a-b-c-d (in a number system with a large base) gives the specificity.
So in your case you have two rules:
.rightColumn * {} /* a = 0, b = 0; c = 1, d = 0 : Specificity = 0010*/
td {} /* a = 0, b = 0, c = 0, d = 1 : Specificity = 0001 */
0001 is lower than 0010 and thus the first rule wins.
There are two ways to fix this:
Use !important to make a rule more "important". I'd avoid doing this because it is confusing when you have lots of rules spread out over several files.
Use a higher-specifity selector for the td you want to modify. You can add a class name to it or an id and this will allow you to supersede the rule from the linked CSS file.
Example:
<style>
.rightColomn * { padding: 0; } /* 0010 */
td#myUnpaddedTable { padding: 10px; } /* 0101 */
td.anUnpaddedTable { padding: 10px; } /* 0011 */
</style>
Edit: Fixed the specificity rules for *. David's comment prompted me to re-read the spec, which does show that the * selector contributes nothing to the specificity score.
As others have mentioned, you have a specificity problem. When determining which of two rules should take precedence, the CSS engine counts the number of #ids in each selector. If one has more than the other, it's used. Otherwise, it continues comparing .classes and tags in the same way. Here, you have a class on the stylesheet rule, but not on the inline rule, so the stylesheet takes precedence.
You can override this with !important, but that's an awfully big hammer to be using here. You're better off improving the specificity of your inline rule. Based on your description, it sounds like your .rightColumn element either is or contains a table and you'd like the cells in that table to have extra spacing? If so, the selector you're looking for is ".rightColumn td", which is more specific than the stylesheet rule and will take precedence.
The easiest way to get it to work is to add "!important" to CSS to guarantee its precedence (unless you've got multiple !important rules):
td {
padding-left: 10px !important;
}
If you're looking for an answer without !important, you should read into CSS specificity specifications. The linked site has a good explanation of how it works, though basically it goes from most important to least, with id selectors most important, class selectors second, and element selectors third.
Try this instead:
td.rightColumn * {margin: 0; padding: 0;}
The td in the external stylesheet is more specific so it wins out. If you qualify the rightColumn class with an element name then the page-level styles will be applied.
You could try adding the ! important flag to your inline css.
e.g.
td { padding-left:10px ! important; }
Also, for general rules on css rule ordering, have a look at this :
http://www.w3.org/TR/CSS2/cascade.html#specificity
Do this:
.rightColumn *,
td.rightColumn * {
margin: 0;
padding: 0;
}
Precedence in CSS is as follows:
If some rule has an ID, then it will precede anything else.
If some rule has a class attribute, it will precede tag-only rules.
If two rules have both IDs or tags, then the number of them untie the "fight".
Example:
<style type="text/css">
#myid{
padding: 10px;
}
.class{
padding: 20px;
}
</style>
<div id="myid" class="class"></div>
Although your div has both ID and a class, the ID rule will override the .class rule.
To read more about CSS rules priorities, I'd recommend http://www.w3.org/TR/CSS2/cascade.html#specificity.
ok i admit i'm kind of late to the game here.. but 3 years on i guess i can still shoot for that first place answer..
the extra sauce in my answer is that there's an exmaple of css with 2 levels of class name..
in the below example you can see the 'td' with no class gets the ".interval td" style and the td with "indragover" class gets the "table.interval td.indragover" style..
(this code comes is for html drag and drop so there's some javascript applying the 'indragover' class to the td in dragenter, dragleave events)
// put this in a css file
.interval {
height: 100%;
width: 100%;
background: #FFFFCC;
border: 2px solid #000000;
border-collapse: collapse;
}
table.interval tr td {
border: 2px solid black;
color:#112ABB;
background: #FFFFCC;
height: 20px;
}
table.interval td.indragover {
background: #AAAA00;
}
// put this in a html file
<table class="interval">
<tr><td>blah</td><td class="indragover">blah</td></tr>
<tr><td class="indragover">blah</td><td>blah</td></tr>
</table>
1.div p.bio {font-size: 14px}
#sidebar p {font-size: 12px}
The first line of CSS might seem more specific at first glance, but it's actually the second line above that would be more specific to the font-size of your paragraph.
An id is more specific than a class, which is more specific than an element.
2.p {font-size: 12px}
p.bio {font-size: 14px}
The second line of CSS (p.bio) is more specific than the first when it comes to your class="bio" paragraph.
the precedence level of class is higher than the p element.

Resources