Is it possible to add a parent selector in LESS? - css

My css is structured in components, each component is stand-alone.
example:
.menu {
background: black;
}
The framework I'm using sometimes adds a class to the body-tag. For example for logged in users it would look like this:
<body class="loggedIn">
<div class="menu"</div>
</body
I would like to keep the css structured inside each component. Is it possible to add a selector in less that is added before the parent? Something like:
.menu{
%loggedIn{
color: red
}
}
should give loggedIn users a red menu.

Unless I am completely missunderstanding you, and there is a possibility, then the ampersand-parent-selector is exactly what you need!
.menu{
.loggedIn & {
color: red
}
}
Should result in
.loggedIn .menu {
color: red
}

You can reference the parent selector using &: http://lesscss.org/features/#parent-selectors-feature
LESS
.menu {
background: black;
.loggedIn & {
color: red
}
}
Will compile to CSS
.menu {
background: black;
}
.loggedIn .menu {
color: red
}

Related

LESS CSS naming convention - Child selectors on hover

In LESS, you can reference a child selector as follows:
<div class="button">
<div class="button-text"> Text </div>
</div>
.button {
&-text {
color:red;
}
}
This will output:
.button .button-text { color:red; }
This is neat and ideal, however, when using a hover, is there a way to maintain the same / similar syntax for the child element? Currently, this wouldn't naturally work:
.button {
&:hover {
&-text {
color:red;
}
}
}
This won't work and as expected, outputs something along the lines of
.button:hover .hover-text { }
Is there a way to get the expected hover result without defining the full class name, in this instance ".button-text"?
Any help would be greatly appreciated.
Because the parents selector & represents all parent selectors (not just the nearest ancestor), nesting under hover, will always include the :hover text.
This rule:
.button {
&:hover &-text {
color:red;
}
}
Will provide the result (lessismore playgroud):
.button:hover .button-text {
color: red;
}

Join multiple CSS files into single one

I had to covert some PSD-s into html, but every page had its own styling so I went forward and made one for each.
The client now requires them to be joined into a single one. Is that possible?
Thanks.
Edit: They don't have unique ID/classes.
Since you converted the PSD's to HTML, I assume you've still got access to the code? In which case, your best best is to give each page a unique identifier (class or ID) at a high enough level that you can specificy with parent / child selectors. Example:
Page 1:
<body id="aboutus">
Page 2:
<body id="services">
You can then target via CSS the elements that are on each page within the same CSS file (the laws of specificity will take effect: https://www.smashingmagazine.com/2007/07/css-specificity-things-you-should-know/):
#aboutus h1 {
color: red;
}
#services h1 {
color: green;
}
Option 2 (Credit to Darren Sweeney):
In addition to adding an id / class to the body element I've mentioned above, you can make the process of adding styles for each page a lot easier by using a CSS preprocessing language such as SASS / SCSS. For example:
SCSS:
#aboutus {
h1 {
color: red;
}
p {
font-size: 10px;
}
a {
text-decoration: underline;
.active {
color: #fff;
}
}
}
#services {
h1 {
color: green;
}
p {
font-size: 15px;
}
a {
text-decoration: underline;
.active {
color: #000;
}
}
}

CSS nesting: inherit from whom?

here is a fiddle with the problem:
https://jsfiddle.net/c2exs2f7/3/
How does the second "blue" stay like the first instance (it should have color: white) without changing the HTML structure?
HTML
<div class="blue">
<div class="content">
<div class="label">blue</div>
<div class="yellow">
<div class="content">
<div class="label">yellow</div>
<div class="blue">
<div class="content">
<div class="label">blue</div>
</div>
</div>
</div>
</div>
</div>
</div>
SCSS
// Skip until...
div {
border-radius: .25em;
padding: .5em;
font-family: helvetica, sans-serif;
}
// ...here:
.blue {
background-color: hsl(220,100%,50%);
.content {
color: white;
}
}
.yellow {
background-color: hsl(60,100%,50%);
.content {
color: hsl(0,0%,10%);
}
}
EDIT #1
Thank you guys for these fast responses!
I am working on a grid system where I am able to nest different grid systems (with different CSS values).
The selectors .yellow .content and .blue .content have the same specificity (20 in this case), therefore the selector that appears later in the stylesheet will override the first one due to the cascading nature of a stylesheet. In this case, the selector .yellow .content is overriding .blue .content, which is why the nested .blue element is black.
One quick solution would be to select nested .blue element with the selector .blue .blue:
Updated Example
.blue,
.blue .blue {
background-color: hsl(220,100%,50%);
.content {
color: white;
}
}
An arguably better approach would be to only select direct .content children elements using the child selector, >:
Updated Example
.blue {
background-color: hsl(220,100%,50%);
> .content {
color: white;
}
}
.yellow {
background-color: hsl(60,100%,50%);
> .content {
color: hsl(0,0%,10%);
}
}
Based on your comments, the ordering/layering of the elements may vary. An alternative solution would be to set the color property on the .blue/.yellow element and then set the color property of the children elements to inherit:
Updated Example - this seems to work for all variants.
.blue {
background-color: hsl(220,100%,50%);
color: white;
.content {
color: inherit;
}
}
.yellow {
background-color: hsl(60,100%,50%);
color: hsl(0,0%,10%);
.content {
color: inherit;
}
}
See https://jsfiddle.net/c2exs2f7/4/
What I did was to enforce inheritance only for the child content classed DIV, not the entire descendance.
Applying the immediate children operator > in the SCSS makes the .content div to consider only its immediate parent color.
Go on and try nesting more DIVs, you will see that it works.
You can't. Not with inherent anyway. Because the second blue will inherent from the yellow. So if u want all blue always have white letters and yellow always black letters. Why not just put:
.blue { color: #fff; }
.yellow { color: hsl(0,0%,10%); }
And you won't need the ".content" wrapper.
I had this same issue where the HTML nesting varies and so it's not possible to make more specific selectors due to overwhelming complexity and non-DRY code.
Here's the solution I came to:
https://jsfiddle.net/cg0u8v1s/
Basically, a systematic approach to the class names is key so you can use a CSS attribute selector reliably (although I'd recommend a more unique naming convention than "color-" as it's too generic.).
Example:
.color-blue {
&,
[class*="color-"] &,
[class*="color-"] [class*="color-"] & {// Only needed if you want a 3rd level of nesting to work.
background-color: blue;
.content {
color: skyblue;
}
}
}
.color-yellow {
&,
[class*="color-"] &,
[class*="color-"] [class*="color-"] & {// Only needed if you want a 3rd level of nesting to work.
background-color: yellow;
.content {
color: brown;
}
}
}
This will output selectors that become more specific with nesting without the need for non-DRY code or having to use !important.
The CSS output will look like this:
.color-blue,
[class*="color-"] .color-blue,
[class*="color-"] [class*="color-"] .color-blue {
// code...
}

CSS Style Individual <div=id

I have a ccs sheet with the usual tags
a. {}
a.hover {}
I also have a div=id "footer" that I want to change the font style but the global a. and a.hover are overriding it even when I add a
#footer{
color: #333333
}
Can I override using this or do I need to try? a.#footer or a.hover:#footer
Basically the #footer as is wont work because of the a. mentioned above even though the other elements are working in the #footer div such as margin...just the font color and hover??
Can someone tell me how to style this and not let the global a. interfere with it?
Many thanks
It's all about the hierarchy of code:
HTML:
<div>
Sample link
<div id="footer">
Footer link
</div>
</div>
CSS:
a {
color: #ebebeb;
}
a:hover {
color: #000;
}
#footer a {
color: #3e3e3e;
}
#footer a:hover {
color: #609;
}
Try this piece of code
#footer a,
#footer a:hover{
color:#333;
}
what is dot after a ?
the correct form is a {} , a:hover {} , a#footer and a:hover #footer
If you are nesting a inside div element you need to use
#footer a {
color: #333333;
}
If you only use #footer {} it will apply the styles to div and a won't inherit the color, so you can also write
#footer {
color: #f00;
}
#footer a {
color: inherit;
}
This is a matter of specificity. Styling the <a> elements directly is more specific then just applying some CSS to the <div id="footer"> element and all of its children. You can target any links within your footer by using
#footer a {
color: #333;
}
Due to the descendant selector this rule itself is more specific than the one you're using for all the other <a> elements outside of the footer.

Is there a way to use css pseudo classes as mixins with lesscss compilers?

I was trying to use a class with psuedo class in the less css mixin
a:link{
color:#138CB4;
text-decoration:none;
}
a:visited{
a:link;
color:#84B6CD;
}
But out put I got is this, which an invalid css
a:link{
color: #138CB4;
text-decoration: none;
}
a:visited{
a: link;
color: #84B6CD;
}
Am I missing something here or mixins don't support pseudo classes yet.
I was a little confused by this at first, too, and found myself jumping through hoops to get it to work. Although your post is old enough that it might pre-date this functionality for all I know.
Anyway, if you're just trying to add additional styles to an existing style via pseudo-selectors, you can use the '&' operator. It works kind of like a 'this' keyword, and turns nesting into a simple combination. So you should be able to do:
a {
color: #138CB4;
text-decoration: none;
&:visited {
color: #84B6CD;
}
}
This should compile out to something like:
a {
color: #138CB4;
text-decoration: none;
}
a:visited {
color: #84B6CD;
}
Note that you can also use the & to combine 'sub-selectors':
.outer {
color: blue;
.error {
//this will select elements that are .error inside-of/descending-from .outer
}
&.error {
//This will select elements that are .outer AND .error
color: red;
}
}
The official definition is unfortunately hiding in plain sight in the Nesting Rules part of the documentation.
I don't believe that is how you use mixin's in Less.
You have defined the link pseudo class and then nested it under the visited pseudo class. This doesn't actually mean anything and is why your are getting that output.
If I think what you are aiming for is to re-use your link styles across :visited and :link, you actually will want this:
.link {
color: #138CB4;
text-decoration: none;
}
a:link {
.link;
}
a:visited{
.link;
color: #84B6CD;
}
Not fully sure, what you want to achieve. But if you got tired of :link,:visted,:active (aka normal link) vs. :focus, :hover (hover styles), this works:
.anchor( #- ) {
a, a:link, a:visited, a:active {
#-();
}
}
.anchorH( #- ) {
a:focus, a:hover {
#-();
}
}
for example:
.anchor({
background: #fff;
});
.anchorH({
background: #ddd; /* darken on hover or focus */
});

Resources