CSS psuedo-element content: attr(type)? - css

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.

Related

Children :before content inheritance

The title might be a little bit confusing but I wonder why is it impossible for a child element to inherit it's parent ::before content. for example:
HTML:
<div class="foo">
<div class="baz"></div>
</div>
CSS:
.foo::before {
content: 'bar';
}
.foo .baz::before {
content: inherit;
}
I have tried it that way, and even this way:
.foo > .baz::before {
content: inherit;
}
and this one:
.foo::before ~ .baz::before {
content: inherit;
}
...and none of the above worked... Is it possible at all? if not, which options do I have in order to achieve this?
UPDATE
I think I might found a way to do such thing:
.foo {
content: 'bar';
}
.foo > .baz,
.foo > .baz::before {
content: inherit;
}
A ::before/::after pseudo-element cannot inherit from another ::before/::after pseudo-element. A pseudo-element can only inherit from its originating element — this is the element that the pseudo-element is attached to. A pseudo-element cannot even inherit from the parent of its originating element, unless the originating element itself is also inheriting from its parent and the property involved is not content.
In your example, .foo::before can only inherit from the .foo it's attached to, and likewise for .baz::before and .baz. .baz::before cannot inherit from .foo::before, so what you're trying to do is not possible. There does not appear to be a reliable way to ensure that one pseudo-element always inherits from another pseudo-element through CSS alone without enforcing this within the markup itself.

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.

Multi-lingual CSS increment counter

How do you change the language in which a CSS counter displays when using alphabetical characters?
.outer {
counter-increment:question;
}
.inner {
content:counter(question, lower-alpha) ".";
}
Use one of the list-style-type settings (there's a whole list on that MDN page):
li {
content:counter(question, lower-alpha) ".";
list-style-type: lower-armenian;
}
http://jsfiddle.net/543aL6my/
Which gives:
Note that the case will follow whatever the list-style-type is, even though you've passed it to counter().
You could just add a language selector to target different languages:
inner:lang(it) {
content:counter(question, lower-alpha) ".";
}
obviously you'd need to also modify markup but it souldn't be too difficult.

LESS CSS selector combining not and :after pseudo element

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';
}

Resources