Sass nth-child nesting - css

I'm refactoring these CSS selectors over to Sass:
#romtest .detailed th:nth-child(2),
#romtest .detailed th:nth-child(4),
#romtest .detailed th:nth-child(6),
#romtest .detailed td:nth-child(2),
#romtest .detailed td:nth-child(3),
#romtest .detailed td:nth-child(6),
#romtest .detailed td:nth-child(7),
#romtest .detailed td.last:nth-child(2),
#romtest .detailed td.last:nth-child(4) {
background:#e5e5e5;
}
...and came up with this:
#romtest .detailed {
th:nth-child {
&(2), &(4), &(6) {
background:#e5e5e5;
}
}
td:nth-child {
&(2), &(3), &(6), &(7) {
background:#e5e5e5;
}
}
td.last:nth-child {
&(2), &(4) {
background:#e5e5e5;
}
}
}
Unfortunately this is throwing an error:
Invalid CSSS after "&": expected "{", was "(2), &(4), &(6) {"
I also know this could be better because I'm:
repeating the background color
repeating numbers - i.e. (2) and (6)
How should I refactor these selectors?

I'd be careful about trying to get too clever here. I think it's confusing as it is and using more advanced nth-child parameters will only make it more complicated. As for the background color I'd just set that to a variable.
Here goes what I came up with before I realized trying to be too clever might be a bad thing.
#romtest {
$bg: #e5e5e5;
.detailed {
th {
&:nth-child(-2n+6) {
background-color: $bg;
}
}
td {
&:nth-child(3n), &:nth-child(2), &:nth-child(7) {
background-color: $bg;
}
&.last {
&:nth-child(-2n+4){
background-color: $bg;
}
}
}
}
}
and here is a quick demo: http://codepen.io/anon/pen/BEImD
----EDIT----
Here's another approach to avoid retyping background-color:
#romtest {
%highlight {
background-color: #e5e5e5;
}
.detailed {
th {
&:nth-child(-2n+6) {
#extend %highlight;
}
}
td {
&:nth-child(3n), &:nth-child(2), &:nth-child(7) {
#extend %highlight;
}
&.last {
&:nth-child(-2n+4){
#extend %highlight;
}
}
}
}
}

You're trying to do &(2), &(4) which won't work
#romtest {
.detailed {
th {
&:nth-child(2) {//your styles here}
&:nth-child(4) {//your styles here}
&:nth-child(6) {//your styles here}
}
}
}

Related

Nested selectors using Sass

How can I have this output using Sass?
.class.active .class-name1 {}
.class.active .class-name2 {}
Here is what I tried :
.class {
&.avtive {
&-name1 {
}
&-name2 {
}
}
}
You need to keep a reference to the outer class name, and interpolate it for your -name classes. Using color: red as an example of the style to apply:
.class {
$outer-class: &;
&.active {
#{$outer-class}-name1 {
color: red;
}
#{$outer-class}-name2 {
color: red;
}
}
}

Syntax for if/else condition in SCSS mixins

I created a SASS #mixin which contains #if conditions to assign styling to elements based on their z-index property to create some sort of elevation.
However what ever I am trying it will not work out.
I'm pretty sure I am doing something just slightly wrong that affects everything else.
I'd appreciate your feedback. Thanks in advance!
$background: #121212;
$surface: #1f1f1f;
$surface-shade_1: #282828;
$surface-shade_2: #303030;
%surface {
background-color: $surface;
}
%surface-shade_1 {
background-color: $surface-shade_1;
}
%surface-shade_2 {
background-color: $surface-shade_2;
}
#mixin elevation($elevationValue) {
#if $elevationValue>0 {
#extend %surface;
}
#else if $elevationValue>4 or $elevationValue=4 {
#extend %surface-shade_1;
}
#else if $elevationValue>8 or $elevationValue=8 {
#extend %surface-shade_2;
}
z-index: $elevationValue * 50;
}
nav {
#mixin elevation(4);
}
If you want to use #mixin inside the CSS files you can use like #include mixin-name and also use directly $elevationValue >= 4 instead of $elevationValue>4 or $elevationValue=4 it becomes much cleaner.
$background: #121212;
$surface: #1f1f1f;
$surface-shade_1: #282828;
$surface-shade_2: #303030;
%surface {
background-color: $surface;
}
%surface-shade_1 {
background-color: $surface-shade_1;
}
%surface-shade_2 {
background-color: $surface-shade_2;
}
#mixin elevation($elevationValue) {
#if $elevationValue > 0 {
#extend %surface;
}
#else if $elevationValue >= 4 {
#extend %surface-shade_1;
}
#else if $elevationValue >= 8 {
#extend %surface-shade_2;
}
z-index: $elevationValue * 50;
}
nav {
#include elevation(4);
}

Reverse states on hover with Less

I have the following LESS code:
.favourite-action-link {
&:after {
color:#grey;
content: '\e836';
}
&.is-favourite:after {
color:#red;
content: '\e811';
}
&:hover {
&:after {
color:#red;
content: '\e811';
}
&.is-favourite:after {
color:#grey;
content: '\e836';
}
}
}
With the essential goal being that there is a normal state and a hover state, that are reversed when another class is present. I'll be repeating this for other actions (eg .share-action-link, .review-action-link etc) and this just seems messy the way I have it. Is there a way to create a mixin such that I could provide this like so:
.favourite-action-link {
&:after {
color:#grey;
content: '\e836';
&:hover {
color:#red;
content: '\e811';
}
.reverseOnClass(is-favourite);
}
}
Or something like that? The only way I can think of so far would be to do:
.favourite-action-link {
&:after {
color:#grey;
content: '\e836';
}
&.active:after {
color:#red;
content: '\e811';
}
}
and then to use jQuery instead to do the hover - toggling .active on (isHovering XOR hasClass(is-favourite)) - but turning LESS into LESS + jQuery is the opposite of fixing a mess/maintainability issue.
I would really recommend writing it like below because it keeps the code simple and easy to read.
.favourite-action-link {
&:after, &.is-favourite:hover:after {
color: #grey;
content: '\e836';
}
&:hover:after, &.is-favourite:after {
color: #red;
content: '\e811';
}
}
But if you really want to use a mixin to avoid repeating the selectors then you could write it like below. This mixin takes two rulesets as input and they are applied to the required selectors.
.favourite-action-link {
.rules-gen(
{
color: #grey;
content: '\e836';
};
{
color: #red;
content: '\e811';
}
);
}
.rules-gen(#rule1; #rule2){
&:after, &.is-favourite:hover:after {
#rule1();
}
&:hover:after, &.is-favourite:after {
#rule2();
}
}
In both these methods, the selectors are also grouped and that also means reduced lines of code.
Demo
Or, if the extra class is not always is-favourite and it could also be something else then you could pass it also to the mixin as a parameter like below:
.favourite-action-link {
.rules-gen(
{
color: grey;
content: '\e836';
};
{
color: red;
content: '\e811';
};
~"is-favourite"
);
}
.share-action-link {
.rules-gen(
{
color: yellow;
content: '\e836';
};
{
color: gold;
content: '\e811';
};
~"active"
);
}
.rules-gen(#rule1; #rule2; #addedClass){
&:after, &.#{addedClass}:hover:after {
#rule1();
}
&:hover:after, &.#{addedClass}:after {
#rule2();
}
}
Demo

SCSS combine :hover and #if

Is it possible to combine the following code and using the :hover selector and #if statement together?
$active: true;
button {
&:hover {
color: red;
}
#if $active {
color: red;
}
}
This is the thing I'd like to do:
button {
&:hover,
& #if $active {
color: red;
}
}
Thanks in advance.
You can actually kind of achieve this using $var: if();. It could look something like this:
$target: if(true, "&", "");
a {
&:hover,
#{$target} {
color: black;
}
}
More info on if() here: http://thesassway.com/news/sass-3-3-released#if

Extending a Nested Placeholder in SCSS

Is it possible to #extend a SCSS placeholder with nesting, and have that nesting reflected in the resulting class?
Given a nested placeholder:
%my-form-field {
...
&__label {
...
}
&__feedback {
...
}
}
I currently have to do the following:
.one-of-many-targets {
#extend %my-form-field;
&__label {
#extend %my-form-field__label;
}
&__feedback {
#extend %my-form-field__feedback;
}
}
But I'd like to be able to simplify this to:
.one-of-many-targets {
#extend %my-form-field;
}
... and have it resolve to:
.one-of-many-targets { ... }
.one-of-many-targets__label { ... }
.one-of-many-targets__feedback { ... }
Is there a different way to write my placeholder and #extends to make the SCSS cleaner, as in the 2nd example?
You can use a mixin instead:
#mixin my-form-field() {
width: 10px;
&__label {
width: 20px;
}
&__feedback {
width: 30px;
}
}
.one-of-many-targets {
#include my-form-field();
}
will generate:
.one-of-many-targets {
width: 10px;
}
.one-of-many-targets__label {
width: 20px;
}
.one-of-many-targets__feedback {
width: 30px;
}
You could try use selector.append()
See: https://github.com/sass/sass/issues/2808#issuecomment-574413393
Also see more info why parent selector didn't work as you expect in extend-only selectors: https://github.com/sass/sass/issues/2262#issuecomment-291645428

Resources