SASS Inheritance with Overrides - css

SASS inheritance with #extend is really useful. Something like this is very easy:
.my-base-class {
font-size: 14px;
}
.my-extended-class {
#extend .my-base-class;
color: red;
}
What I would like to be able to do, however, is to redefine rules in .my-extended-class that are defined in .my-base-class. Something like this:
.my-base-class {
font-size: 14px;
}
.my-extended-class {
#extend .my-base-class;
font-size: 18px;
}
In this instance, the font-size is redefined to be 18px in .my-extended-class.
I do realize that I could just add !important to the font-size in .my-extended-class. However, I don't want to do this for two main reasons. #1 I've been taught to avoid !important whenever possible. #2 I actually want to override fairly complex nested properties. Something like this:
.my-base-class {
font-size: 14px;
.child-of-my-base-class {
margin: 10px;
padding: 5px;
background-color: green;
}
}
.my-extended-class {
#extend .my-base-class;
font-size: 18px;
.child-of-my-base-class {
background-color: purple;
}
}
Is something like this possible?
Thanks.
Aaron

Thanks to #BlueCaret for the jsfiddle.
It looks like SASS does indeed do this out of the box; it's just my web compiler in Visual Studio that is broken.
So, question answered. Thanks.
Aaron

Related

Sass/SCSS: Overwrite and only render the overwritten props [duplicate]

Ok so I have a placeholder with a nested selector:
%block {
.title {
font-size:12px;
}
}
I want to extend it and ADD to the .title class:
.superblock {
#extend %block;
.title {
font-weight:bold;
}
}
The answer I WANT is this:
.superblock .title {
font-size: 12px;
font-weight: bold; }
However, the answer I get is this:
.superblock .title {
font-size: 12px; }
.superblock .title {
font-weight: bold; }
Am I doing something wrong or is this just how it works? To clarify I want to merge it. If I add something directly inside the .superblock and add like another .superblock2 which also extends %block they merge without any problems.
Sass has no functionality for "merging" duplicate selectors. You'll need to find another utility to do this after the CSS has been compiled.
The #extend directive isn't just a way to use classes in place of mixins (similar to LESS style mixin calls). Why #extend works the way it does becomes clear when you're extending normal classes instead of extend classes:
.block {
font-size:12px;
}
.foo {
#extend .block;
font-weight: bold;
}
Output:
.block, .foo {
font-size: 12px;
}
.foo {
font-weight: bold;
}
Using an extend class just suppresses the emission of the original class name.
Now that you've seen why #extend works the way it does, do you still want what #extend offers? If the answer is no, then you need to use a mixin:
#mixin block {
// styles
.title {
font-size: 12px;
#content;
}
}
.superblock {
#include block {
font-weight: bold;
}
}
Output:
.superblock .title {
font-size: 12px;
font-weight: bold;
}
This is pretty much it. SASS produces extended declarations separately.
And it has no functionality of grouping declarations by selector, it's not that smart.
But you need not worry that much about CSS cleanness. Modern web servers serve CSS gzipped, all duplication will be nicely compressed.
LESS can do that. However you would write:
.superblock {
.title {
.block .title;
}
}
Not sure if it works with #extend too.
You can use a tools, I used it to clean the css
https://github.com/addyosmani/grunt-uncss
"A grunt task for removing unused CSS from your projects with UnCSS."

Not able to extend Less mixin

I would like to have below CSS output using Less
.selected-values,
.selected-values a {
background-color: #505050;
color: #fff;
}
.selected-values {
display: block;
}
.selected-values a {
text-decoration: none;
}
So far i have thought of below Less syntax, but it is not working.
.selected-dropdown-values() {
background-color: #505050;
color: #fff;
}
.selected-values:extend(.selected-dropdown-values) {
display: block;
}
.selected-values a:extend(.selected-dropdown-values) {
text-decoration: none;
}
I am not able to apply any extend logic to generate this syntax. I might be missing something or i am unaware about how to do it properly in Less. Also, I do not want .selected-dropdown-values mixin to output in CSS.
As mentioned in comments and discussed in the chat, Less currently does not support extending of mixins (there is a request and it might get addressed in v2.0.0 or later). (Note: To be more precise with wordings, extending of mixins which are not output in CSS is not supported.)
So, the best way forward would be to do the below:
Less:
.selected-dropdown-values { // just remove the braces
background-color: #505050;
color: #fff;
}
Just remove the braces from the .selected-dropdown-values rule. Ofcourse this would cause that rule also to be present in the CSS output but given that we are using extend, it would mean only one extra line in CSS output.
Output:
.selected-dropdown-values,
.selected-values,
.selected-values a {
background-color: #505050;
color: #fff;
}

merge several class into one single class [duplicate]

Ok so I have a placeholder with a nested selector:
%block {
.title {
font-size:12px;
}
}
I want to extend it and ADD to the .title class:
.superblock {
#extend %block;
.title {
font-weight:bold;
}
}
The answer I WANT is this:
.superblock .title {
font-size: 12px;
font-weight: bold; }
However, the answer I get is this:
.superblock .title {
font-size: 12px; }
.superblock .title {
font-weight: bold; }
Am I doing something wrong or is this just how it works? To clarify I want to merge it. If I add something directly inside the .superblock and add like another .superblock2 which also extends %block they merge without any problems.
Sass has no functionality for "merging" duplicate selectors. You'll need to find another utility to do this after the CSS has been compiled.
The #extend directive isn't just a way to use classes in place of mixins (similar to LESS style mixin calls). Why #extend works the way it does becomes clear when you're extending normal classes instead of extend classes:
.block {
font-size:12px;
}
.foo {
#extend .block;
font-weight: bold;
}
Output:
.block, .foo {
font-size: 12px;
}
.foo {
font-weight: bold;
}
Using an extend class just suppresses the emission of the original class name.
Now that you've seen why #extend works the way it does, do you still want what #extend offers? If the answer is no, then you need to use a mixin:
#mixin block {
// styles
.title {
font-size: 12px;
#content;
}
}
.superblock {
#include block {
font-weight: bold;
}
}
Output:
.superblock .title {
font-size: 12px;
font-weight: bold;
}
This is pretty much it. SASS produces extended declarations separately.
And it has no functionality of grouping declarations by selector, it's not that smart.
But you need not worry that much about CSS cleanness. Modern web servers serve CSS gzipped, all duplication will be nicely compressed.
LESS can do that. However you would write:
.superblock {
.title {
.block .title;
}
}
Not sure if it works with #extend too.
You can use a tools, I used it to clean the css
https://github.com/addyosmani/grunt-uncss
"A grunt task for removing unused CSS from your projects with UnCSS."

SCSS extend a nested selector and override the nested rulesets

Ok so I have a placeholder with a nested selector:
%block {
.title {
font-size:12px;
}
}
I want to extend it and ADD to the .title class:
.superblock {
#extend %block;
.title {
font-weight:bold;
}
}
The answer I WANT is this:
.superblock .title {
font-size: 12px;
font-weight: bold; }
However, the answer I get is this:
.superblock .title {
font-size: 12px; }
.superblock .title {
font-weight: bold; }
Am I doing something wrong or is this just how it works? To clarify I want to merge it. If I add something directly inside the .superblock and add like another .superblock2 which also extends %block they merge without any problems.
Sass has no functionality for "merging" duplicate selectors. You'll need to find another utility to do this after the CSS has been compiled.
The #extend directive isn't just a way to use classes in place of mixins (similar to LESS style mixin calls). Why #extend works the way it does becomes clear when you're extending normal classes instead of extend classes:
.block {
font-size:12px;
}
.foo {
#extend .block;
font-weight: bold;
}
Output:
.block, .foo {
font-size: 12px;
}
.foo {
font-weight: bold;
}
Using an extend class just suppresses the emission of the original class name.
Now that you've seen why #extend works the way it does, do you still want what #extend offers? If the answer is no, then you need to use a mixin:
#mixin block {
// styles
.title {
font-size: 12px;
#content;
}
}
.superblock {
#include block {
font-weight: bold;
}
}
Output:
.superblock .title {
font-size: 12px;
font-weight: bold;
}
This is pretty much it. SASS produces extended declarations separately.
And it has no functionality of grouping declarations by selector, it's not that smart.
But you need not worry that much about CSS cleanness. Modern web servers serve CSS gzipped, all duplication will be nicely compressed.
LESS can do that. However you would write:
.superblock {
.title {
.block .title;
}
}
Not sure if it works with #extend too.
You can use a tools, I used it to clean the css
https://github.com/addyosmani/grunt-uncss
"A grunt task for removing unused CSS from your projects with UnCSS."

Wrapping css without bloating css file

I was wondering if something like this can be done in CSS. I want to be able to group css so that I can I don't have to write it like this.
.wrapper .header {do: something};
.wrapper .nav .firstMenuItem {do: something};
[div id="wrapper"]
[div class="header"]
[div class="nav"]
[ul]
[li class="firstMenuItem">First Item</li]
[/ul]
[/div]
[/div]
[/div]
Instead, I would like to do something like this but I've never seen it being used like this
.wrapper
{
.header .nav {do:something;}
.header .nav .firstMenuItem
{
do: something;
}
}
You can do this with LESS and SASS
However, before going too far down this road I recommend you read a little about Object Oriented CSS. (Some good tips from people who have experience with large projects)
LESS example:
#header {
color: black;
.navigation {
font-size: 12px;
}
.logo {
width: 300px;
&:hover { text-decoration: none }
}
}
SASS example:
.error {
border: 1px #f00;
background: #fdd;
}
.error.intrusion {
font-size: 1.3em;
font-weight: bold;
}
.badError {
#extend .error;
border-width: 3px;
}
You can't do that with pure CSS, but you can use something like:
LESS
SCSS
Not with CSS alone, but you can for example use LESS which provides this kind of nesting.
I'm afraid that is just not possible in classic CSS. It is against the syntax.
There to exist interpreters for alternative syntaxes, which will just turn your syntax into valid CSS either at compile-time or run-time. You could look for or write one of those.
But if you want what you write to be valid CSS, this is just not possible.

Resources