LESS CSS selector combining not and :after pseudo element - css

I have 3 main elements: .submit-it, .send-it, .get-results.
I want all of their :after elements to have certain styling EXCEPT if they have the classes excluded, or error. I thought this would work, but it doesn't.
.submit-it, .send-it, .get-results {
&:not(.excluded), &:not(.error) {
&:after {
content: 'text';
}
}
}

By generating the following selectors, you are essentially styling all :after pseudo elements regardless of their classes.
.submit-it:not(.excluded):after,
.submit-it:not(.error):after, { ... }
By selecting all elements without class excluded, and all elements without class error, you are indirectly selecting all the elements since these two events are not mutually exclusive.
Therefore you would chain the :not() pseudo classes, and replace:
&:not(.excluded), &:not(.error)
with:
&:not(.excluded):not(.error)
.submit-it, .send-it, .get-results {
&:not(.excluded):not(.error) {
&:after {
content: 'text';
}
}
}
Which will output:
.submit-it:not(.excluded):not(.error):after,
.send-it:not(.excluded):not(.error):after,
.get-results:not(.excluded):not(.error):after {
content: 'text';
}

Related

Is it possible to include the pseudo element inside it's parent element css

I would like to format my css such that each relevant element is within their own class, including the class's pseudo-elements.
Currently, the pseudo-element is formatted this way.
element {
...
}
element::after {
...
}
Is it possible to format the above into this format? Basically nesting the pseudo-element inside it's parent element.
element {
...
element::after {
...
}
}
Not with vanilla css.
You have a few options, such as Scss, Less, Stylus and Postcss(with a plugin).
If you're just starting, I'd recommend Scss:
.element {
&::after {
}
}

Less cascading & refactoring

I am trying to refactor some css looking like this:
path.myClass {
//some CSS
}
.someOtherClass.myClass {
//some other CSS
}
I am struggling to find the right syntax for the first part. I am trying to have something looking like this:
.myClass {
path.& {
// some CSS
}
.someOtherClass {
// some other CSS
}
}
How can I refactor this correctly?
You can do it like below. Since the top level selector already has . there is no need to add it again before the parent selector (&) in the inner selector. The second one is fairly straightforward as you can append the parent selector either at the start or at the end. The order of classes doesn't matter.
(Note: There should be no space before the parent selector as it would change the meaning.)
.myClass {
path&{
color: red;
}
.someOtherClass& { /* can do &.someOtherClass also, order doesn't matter */
color: blue;
}
}
Below is the compiled CSS output:
path.myClass {
color: red;
}
.someOtherClass.myClass {
color: blue;
}

Sass back nesting issue

I'm trying to figure out how to back nest specifically to the parent of the css nest I'm in. Meaning, my current set up is a parent class to a span to a before pseudo. I need to change a style on the pseudo based on a modifier on the parent. If I do this:
.parent {
span {
&:before {
// styles
.modifier & {
// Other styles
}
}
}
}
The output is .modifier .parent span:before What I need is .parent.modifier span:before
Isn't there a way to do this without adding the modifier to the parent and pathing to the pseudo again? This is what I want to avoid.
.parent {
span {
&:before {
// styles
}
}
&.modifier {
span {
&:before {
// Other Styles
}
}
}
}
This is certainly possible, it does require the use of some of the less known sass functions #at-root, & ampersand and string interpolation #{}.
Basically it works in the following manner;
Use #at-root to jump outside of the class, to the 'root'.
We place our class after that, I've used .--modifer-is-red.
We attach the classes that we jumped outside of by using interpolation of the &, #{&}.
Live Example
Example used for clarity
.parent {
span {
&:before {
// styles
color: black;
// Modifiers attached to the parent
#at-root .--modifier-is-red#{&} {
color: red;
}
}
}
}
// output
// .--modifier-is-red.parent span:before {
// color: red;
// }
Exact example to reflect your code
.parent {
span {
&:before {
// styles
#at-root .modifier#{&} {
// Other styles
}
}
}
}
There is some limitations to this, also it does look slightly odd that the modifier is placed before the parent in the output, but the browser doesn't mind.
I hope this solves your problem.
Isn't there a way to do this without adding the modifier to the parent and pathing to the pseudo again?
No, because you only have the & variable to work with, which is always a single unit consisting of the entire complex selector. You can't specify where exactly in the middle of the complex selector you want your modifier to go. The best you can do is attach it as a compound selector or use it with a combinator.

CSS psuedo-element content: attr(type)?

I just want a rule that acts like so:
div:before {
content: "div";
}
span:before {
content: "span";
}
a:before {
content: "a";
}
but I want it to be generic for all element types, not just a div.
I want this...
*:before {
content: attr(tagname);
}
But tagname is not an attribute. Is there any way to get the element's type as a string in CSS?
No, there is no way. Generated content can be specified in a few ways only. What you are trying to do requires client-side scripting, perhaps so that CSS rules are dynamically added to elements, and in the script code, you can use the tag name from the element node.

LESS CSS nesting classes

I'm using LESS to improve my CSS and am trying to nest a class within a class. There's a fairly complicated hierarchy but for some reason my nesting doesn't work.
I have this:
.g {
float: left;
color: #323a13;
.border(1px,#afc945);
.gradient(#afc945, #c8da64);
.common;
span {
.my-span;
.border-dashed(1px,rgba(255,255,255,0.3));
}
.posted {
.my-posted;
span {
border: none;
}
}
}
I can't get the .g.posted to work. it just shows the .g bit.
If i do this it's fine:
.g {
float: left;
color: #323a13;
.border(1px,#afc945);
.gradient(#afc945, #c8da64);
.common;
span {
.my-span;
.border-dashed(1px,rgba(255,255,255,0.3));
}
}
.g.posted {
.my-posted;
span {
border: none;
}
}
I'd like to nest the .posted in .g though. Any ideas?
The & character has the function of a this keyword, actually (a thing I did not know at the moment of writing the answer). It is possible to write:
.class1 {
&.class2 {}
}
and the CSS that will be generated will look like this:
.class1.class2 {}
For the record, #grobitto was the first to post this piece of information.
[ORIGINAL ANSWER]
LESS doesn't work this way.
.class1.class2 {} - defines two classes on the same DOM node, but
.class1 {
.class2 {}
}
defines nested nodes. .class2 will only be applied if it is a child of a node with the class class1.
I've been confused with this too and my conclusion is that LESS needs a this keyword :).
.g {
&.posted {
}
}
you should add "&" before .posted
If the ampersand is located right next to the child element in nesting, it is compiled into a double class selector. If there is space between & and selector it will be compiled into child selector. Read more about nesting in Less here.

Resources