Mix css modules classes and boostrap active - css

In a project I am working on we use css modules with postcss (also postcss-cssnext and postcss-include). We also have bootstrap as a dependency which is globally provided.
In a given component I do have a custom class for a button. So my button has the following classes: btn btn-custom.
According to the requirements I want to modify the appearance of the button when it is in an active state. For that bootstrap has the following selector: .btn.active, .btn:active. Overwriting the pseudoclass is the easy part. The .active class though is where it gets tricky.
In my css file I have tried several ways to handle this but none seems to work. Here are some of the things I've tried:
.btn-custom {
&.active, &:active {}
#nested :global &.active, &:active {}
#nested :global & { &.active, &:active: {} }
#nested :global { &.active, &:active: {} }
}
:global {
.btn-custom { &.active, &:active {} }
.btn { &.active, &:active {} }
}
Has anyone any idea on how this could be achieved?

Global targeted classes needs to be wrapped in parens, like so:
.btn-custom {
color: red;
}
.btn-custom:global(.active) {
color: blue;
}
So with nesting:
.btn-custom {
&:global(.active),
&:active {}
}
That last one is untested, I guess the order of PostCSS plugins is important here.

Related

With scss #extend pseudo selected 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;
}

What does this mixin mean?

In a scss file, I saw the below code snippet:
#mixin myMixin() {
:global(.rtl) & {
#content;
}
}
I understand the keywords #mixinas well as #content and tried to understand :global() from this link:
What does :global (colon global) do?.
But I am not sure what "&" does here or what this whole mixin does.
The ampersand (&) is a combinator used in nesting and in this case it is being used to qualify a selector.
For a general example:
// This Sass...
.foo {
.bar & {
color: red;
}
}
// ...would compile to this CSS
.bar .foo { color:red; }
In your example, the mixin declaration replaces .foo, and would look like:
// If you called your mixin at .bar
.bar {
#include myMixin {
color: red;
}
}
// It should compile to something like this
:global(.rtl) .bar { color: red; }
More details about ampersands and qualifying selectors in this CSS Tricks article.

SASS - How can I assign two classes the same style except one property?

I have a SASS stylesheet and I want to assign the same styles for two classes (.class and .otherclass) except for one property (before:) which should have another value for .otherclass.
This is the code I currently have:
.class, .otherclass {
p { font-family:arial;
&before:
#extend .class-one {}
}
~ .extraclass {}
}
Thanks
To be quite honest I'm not sure why u don't want to write two different selectors, or just overide some property in second one. E.g
.class1, .class2, .class3 {
&:before{
content: 'class';
}
}
.class2:before {
content: 'class2';
}
Maybe using :not selector would be helpfull:https://www.w3schools.com/cssref/sel_not.asp
.class1, .class2, .class3 {
&:before {
content: 'class'
}
&:not(.class1):before{
content: 'class23'
}
}
Please try to look like:
.test{
$color:#f00;
}
.demo{
&:extend(.test);
}

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.

Resources