With scss #extend pseudo selected CSS - css

One can do #extend .foo but apparently not #extend .foo:focus.
I'm dealing with a 3rd party component which adds it's own focused class when it considers it is focused. Using #extend to apply Bootstrap styles works fine, but because the 3rd party component does not get a :focus the .form-control:focus is never matched.
My SCSS in principal would be:
.thirdparty {
#extend .form-control;
}
.thirdparty.thirdparty-focused {
#extend .form-control:focus;
}
#extend .form-control:focus; does not compile however.
Currently I can't figure out how to do this without copying the .form-control:focus CSS into .thirdparty.thirdparty-focused, which is obviously rather unideal.
Is some sort of #extend .form-control:focus; equivalent possible, and if not, any suggestions better than copying N lines of CSS to match the rest of Bootstrap?

#extend .form-control:focus will act as a selector, specifically looking for a rule named .form-control:focus. Here is an illustration.
The best solution to your problem would be to outsource the :focus pseudo-selector of the original Bootstrap class, using the %-selector, and then re-extend it into it - so that you could call it seperately.
%focus {
color: #2196f3;
}
.base {
color: #000;
&:focus {
#extend %focus;
}
}
div {
#extend .base;
&.focus {
#extend %focus;
}
}
// Other Bootstrap components can still call `#extend .base;`
This will compile to:
.base:focus, div:focus, div.focus {
color: #2196f3;
}
.base, div {
color: #000;
}

When I tried this, the error message basically told me what to do:
SassError: compound selectors may no longer be extended.
Consider `#extend .form-control, :focus` instead.
Using this should work (don't forget necessary imports to bootstrap):
.thirdparty.thirdparty-focused {
#extend .form-control, :focus;
}

Related

Sass: placeholder behaviour for selectors

I'm having some trouble understanding the placeholder behavior for selectors when compiled into css. So I've created a placeholder inside a class selector (.test) and I'm trying to extend it into another class (.test1) inside a third class (.test2). it compiled into css without any error although I'm curious how the selectors formed when compiled. here are the output and code snippets.
This is not actual use case but I'm just wondering how the selectors formed in the output?
.test {
%placeholder {
font-size: 14px;
}
}
.test2 {
.test1 {
#extend %placeholder;
}
}
Output
.test .test2 .test1, .test2 .test .test1 {
font-size: 14px;
}

#extend class declared after

good day all. I'm using stylus and have the following css structure:
main.styl
#import '_file1'
.myClass {
color: blue
}
file1.styl
.left {
#extend .myClass
background: white
}
This returns an error because .myClass is defined after the #extend. is there a way to correctly use it that way?
Thanks
I think its impossible. It's against to sass logic.

How to extend css class with another style?

I have nearly 30 classes and I want to apply this classes to my button element. I don't want to add class attribute for every button element. Is there any way to create a new button class like;
.button{
.rounded-corner
.corner
.button-effective
//another 20 classes
}
You will have to use a CSS preprocessor to do this.
SASS
placeholder
%rounded-corner {}
%corner {}
%button-effective {}
.button {
#extend %rounded-corner;
#extend %corner;
#extend %button-effective;
/* Some other styles. */
}
.box {
#extend %rounded-corner;
}
Compiles to:
.button, .box {
/* rounded-corner styles */
}
.button {
/* corner styles here */
}
.button {
/* button-effective styles here */
}
.button {
/* Some other styles. */
}
/*
`.box` is NOT defined here because it only uses placeholders. So it
is placed where the placeholder is defined.
*/
Note: with placeholders, the CSS selector is added to wherever the placeholder is defined. Not where the selector is defined.
extend
.rounded-corner {}
.corner {}
.button-effective {}
.button {
#extend .rounded-corner;
#extend .corner;
#extend .button-effective
// Continue with other classes.
}
Compiles to:
.rounded-corner, .button {}
.corner, .button {}
.button-effective, .button {}
mixin
#mixin rounded-corner {}
#mixin corner {}
#mixin button-effective {}
.button {
#include .rounded-corner;
#include .corner;
#include .button-effective
// Continue with other classes.
}
Compiles to:
.button {
/* rounded-corner styles here */
/* corner styles here */
/* button-effective styles here */
}
LESS
LESS has a similar sytanx to SASS and also has extend and mixin, though LESS is a little more forgiving if you want to add one class' style to another. While I believe still considered a mixin in LESS, you can add one class style to another like the following without having to use a keyword.
.rounded-corner {}
.corner {}
.button-effective {}
.button {
.rounded-corner;
.corner;
.button-effective;
// Continue with other classes.
}
Compiles to:
.button {
/* rounded-corner styles here */
/* corner styles here */
/* button-effective styles here */
}
It will be possible in CSS4:
:root {
--toolbar-theme: {
border-radius: 4px;
};
--toolbar-title-theme: {
color: green;
};
}
.toolbar {
#apply --toolbar-theme;
#apply --toolbar-title-theme;
}
For now, you need to use Sass/Less preprocessors.
You could use the attribute selector and concatenate your classes; it would still involve adding a long class to your button element:
<button class="button-rounded-corner-effective">Your button</button>
OR
<button class="button rounded corner effective">Your button</button>
/* Which is exactly what you did not want to do,
but the CSS below will apply all the same.
This example to clarify, then. */
... and then your CSS will be:
[class*="button"]{/*Generic button styles*/}
[class*="rounded"]{/*Rounded styles*/}
[class*="corner"]{/*Corner styles*/}
[class*="effective"]{/*Effective styles*/}
You will need to be careful about the namespacing though - the wild card selector will match any class that has that matches the string.
For example:
[class*="round"]{/*Will match rounded*/}
With CSS modules, you can use composes:
.className {
color: green;
background: red;
}
.otherClassName {
composes: className;
color: yellow;
}
Yes you can use Less or Sass. For me, Less is "easier" to integrate to your project and you will have this code :
.button{
.rounded-corner
.corner
.button-effective
}
.secondClass{
.button;
// your style code
}
.thirdClass{
.button;
// your style code
}
You are describing a mixin or an extends, which is possible currently if you use a CSS Preprocessor like LESS or SASS. CSS Preprocessors allow you to write non-CSS with extra features, and then run it through the preprocessor to convert it into regular CSS which is given to the browser.
It's not possible in regular CSS to do what you are describing.
With CSS modules, you can also compose extending classes from other CSS module by pointing a file:
.otherClassName {
composes: className from "./style.css";
color: yellow;
}

Is there a way to write custom selectors in LESS?

I'll give an example of what I'd like to do.
:all() {
&,
&:link,
&:visited,
&:active,
&:focus
}
The above is an imagining of a 'custom selector' that itself returns a selection of all pseudo-classes of an anchor tag, minus :hover.
I'd like to use it as a selector like so:
.menu {
a.top-level:all, span {
color: #dormant-grey;
}
a.top-level:hover {
color: #off-black;
}
}
And for it to generate:
.menu a.top-level,
.menu a.top-level:link,
.menu a.top-level:visited,
.menu a.top-level:active,
.menu a.top-level:focus,
.menu span {
color: #686868;
}
.menu a.top-level:hover {
color: #22282a;
}
So I hope I'm communicating clearly what the question is. Is there a way to reuse selections?
Note that this is different than passing styles into a mixin. Passing styles into a mixin, to achieve the same thing, would require repeating the styling. Once to pass into the mixin, and then again for all the other selections that the mixin does not handle. Its also what I'm doing now and I'm finding that it isn't worth using the mixin because I've had to repeat myself so many times that I'm just going to pull it out.
So I hope that is clear. I'm asking if there is a way to reuse a selection, not a style. If less can't do it, is there a language that can?
(So to not leave this one w/o an answer - copying my comment above):
.all(#-) {
&,
&:link,
&:visited,
&:active,
&:focus {
#-();
}
}
.menu {
.span {
color: red;
}
a.top-level {
.all({.span});
:hover {
color: blue;
}
}
}
This obviously produces duplicated styles for .span and a.top-level family but as soon as you care and generate a minified CSS version --clean-css --clean-option=--advanced option will eliminate duplicated styles with love.

Nesting CSS classes

Can I do something like the following?
.class1{some stuff}
.class2{class1;some more stuff}
Update 1: There is a CSS3 spec for CSS level 3 nesting. It's currently a draft.
https://tabatkins.github.io/specs/css-nesting/
Update 2 (2019): We now have a CSSWG editors draft
https://drafts.csswg.org/css-nesting-1/
Update 3 (2022): We now have a W3C First Public Working Draft https://www.w3.org/TR/css-nesting-1/
If approved, the syntax would look like this:
table.colortable {
& td {
text-align:center;
&.c { text-transform:uppercase }
&:first-child, &:first-child + td { border:1px solid black }
}
& th {
text-align:center;
background:black;
color:white;
}
}
.foo {
color: red;
#nest & > .bar {
color: blue;
}
}
.foo {
color: red;
#nest .parent & {
color: blue;
}
}
Not possible with vanilla CSS. However you can use something like:
Sass
Sass makes CSS fun again. Sass is an
extension of CSS3, adding nested
rules, variables, mixins, selector
inheritance, and more. It’s translated
to well-formatted, standard CSS using
the command line tool or a
web-framework plugin.
Or
Less
Rather than constructing long selector
names to specify inheritance, in Less
you can simply nest selectors inside
other selectors. This makes
inheritance clear and style sheets
shorter.
Example:
#header {
color: red;
a {
font-weight: bold;
text-decoration: none;
}
}
Not with pure CSS. The closest equivalent is this:
.class1, .class2 {
some stuff
}
.class2 {
some more stuff
}
Not directly. But you can use extensions such as LESS to help you achieve the same.
No.
You can use grouping selectors and/or multiple classes on a single element, or you can use a template language and process it with software to write your CSS.
See also my article on CSS inheritance.
I do not believe this is possible. You could add class1 to all elements which also have class2. If this is not practical to do manually, you could do it automatically with JavaScript (fairly easy to do with jQuery).
If you cannot wait until native CSS nesting goes official, you can use Container Queries to do it. As of now, it is supported (partially) by Chrome & Edge 105+, as well as Safari 16+.
It will looks like this:
.class1 {
container-type: inline-size;
container-name: my-container;
// other style rules
}
#container my-container (min-width: 0px) {
.class2 {
// some style rules
}
}
More details can be found at here.
Try this...
Give the element an ID, and also a class Name. Then you can nest the #IDName.className in your CSS.
Here's a better explanation
https://css-tricks.com/multiple-class-id-selectors/

Resources