Mixin for data-overlay selector - css

Is there a way to convert the following CSS rules to a Mixin or make it a bit more SCSS?
[data-overlay]:before {
content: '';
position: absolute;
background: #000;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 0;
}
[data-overlay="0"]:before {
opacity: 0;
}
[data-overlay="1"]:before {
opacity: 0.1;
}
[data-overlay="2"]:before {
opacity: 0.2;
}

Sassmeister demo.
Sass for loop.
#mixin overlays($count: 0) {
[data-overlay]:before {
content: '';
position: absolute;
background: #000;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 0;
}
#for $i from 0 through $count {
[data-overlay="#{$i}"]:before {
opacity: $i / 10;
}
}
}
#include overlays(4);

Related

How do I shorten this CSS which has CSS Pseudo-elements using SCSS?

How do I shorten this CSS which has CSS Pseudo-elements using SCSS?
.bar-color1 {
background: #28A745;
position: absolute;
top: 0; bottom: 0; left: 0;
&::after {
color: #28A745;
content: url("../../assets/images/arrow.png");;
display: inline-block !important;
width: 0;
height: 0;
position: absolute;
right: 6px;
top: -6px;
}
}
.bar-color2 {
background: #28A745;
position: absolute;
top: 0; bottom: 0; left: 0;
&::after {
content: "" !important;
}
}
As you can see both has these common styles
background: #28A745;
position: absolute;
top: 0; bottom: 0; left: 0;
I think it's better to have a parent class like bar like bellow:
.bar {
background: #28A745;
position: absolute;
top: 0; bottom: 0; left: 0;
&-color1::after {
color: #28A745;
content: url("../../assets/images/arrow.png");;
display: inline-block !important;
width: 0;
height: 0;
position: absolute;
right: 6px;
top: -6px;
}
&-color2::after {
content: "" !important;
}
}
You can use multiple selector:
.bar-color1, .bar-color2 {
background: #28A745;
position: absolute;
top: 0; bottom: 0; left: 0;
}
CSS
.bar-color1, .bar-color2 {
background: #28A745;
position: absolute;
top: 0; bottom: 0; left: 0;
}
.bar-color1 {
&::after {
color: #28A745;
content: url("../../assets/images/arrow.png");;
display: inline-block !important;
width: 0;
height: 0;
position: absolute;
right: 6px;
top: -6px;
}
}
.bar-color2 {
&::after {
content: "" !important;
}
}
Use mixins:
#mixin customStyle {
background: #28A745;
position: absolute;
top: 0; bottom: 0; left: 0;
}
Then use it like so:
.bar-color1 {
#include customStyle();
}
.bar-color2 {
#include customStyle();
}
More on mixins here.

How can I dinamically change the nth-child() property in SASS?

Good evening,
I'm currently working on a designing project and looking to get something like this : Menu
To do so I used this code in SASS :
&:nth-child(1){
left: 10px;
}
&:nth-child(2){
left: 15px;
}
&:nth-child(3){
left: 30px;
}
&:nth-child(4){
left: 35px;
}
&:nth-child(5){
left: 50px;
}
&:nth-child(6){
left: 55px;
}
&:nth-child(7){
left: 70px;
}
&:nth-child(8){
left: 75px;
}
&:nth-child(9){
left: 50px;
}
&:nth-child(10){
left: 55px;
}
&:nth-child(11){
left: 30px;
}
&:nth-child(12){
left: 35px;
}
&:nth-child(13){
left: 10px;
}
&:nth-child(14){
left: 15px;
}
Right now, it is hard-coded, and the layout is not the same if the numbers of elements from the list is different.
So I'd like to do this dynamically, how can I do so?
I thank you in advance for your help,
Alex
Few exemple that might help you going:
How to create a simple loop with pattern
#for $i from 1 through 20 {
li:nth-child(#{$i}) {
left: 25px + $i * 10px; // could be anything, you need to find the pattern
}
}
Compiles to:
li:nth-child(1) {
left: 35px;
}
li:nth-child(2) {
left: 45px;
}
li:nth-child(3) {
left: 55px;
}
li:nth-child(4) {
left: 65px;
}
li:nth-child(5) {
left: 75px;
}
li:nth-child(6) {
left: 85px;
}
li:nth-child(7) {
left: 95px;
}
li:nth-child(8) {
left: 105px;
}
li:nth-child(9) {
left: 115px;
}
li:nth-child(10) {
left: 125px;
}
li:nth-child(11) {
left: 135px;
}
li:nth-child(12) {
left: 145px;
}
li:nth-child(13) {
left: 155px;
}
li:nth-child(14) {
left: 165px;
}
li:nth-child(15) {
left: 175px;
}
li:nth-child(16) {
left: 185px;
}
li:nth-child(17) {
left: 195px;
}
li:nth-child(18) {
left: 205px;
}
li:nth-child(19) {
left: 215px;
}
li:nth-child(20) {
left: 225px;
}
How to create a loop whith a more complex pattern
#for $i from 1 through 20 {
#if ($i < 11) {
li:nth-child(#{$i}) {
left: 25px + $i * 10px; // could be anything
}
}
#else {
li:nth-child(#{$i}) {
left: (25px + (10 * 10px)) - ((11 - $i) * -1) * 10px; // could be anything
}
}
}
Compiles to:
li:nth-child(1) {
left: 35px;
}
li:nth-child(2) {
left: 45px;
}
li:nth-child(3) {
left: 55px;
}
li:nth-child(4) {
left: 65px;
}
li:nth-child(5) {
left: 75px;
}
li:nth-child(6) {
left: 85px;
}
li:nth-child(7) {
left: 95px;
}
li:nth-child(8) {
left: 105px;
}
li:nth-child(9) {
left: 115px;
}
li:nth-child(10) {
left: 125px;
}
li:nth-child(11) {
left: 125px;
}
li:nth-child(12) {
left: 115px;
}
li:nth-child(13) {
left: 105px;
}
li:nth-child(14) {
left: 95px;
}
li:nth-child(15) {
left: 85px;
}
li:nth-child(16) {
left: 75px;
}
li:nth-child(17) {
left: 65px;
}
li:nth-child(18) {
left: 55px;
}
li:nth-child(19) {
left: 45px;
}
li:nth-child(20) {
left: 35px;
}
How to create a loop from a list of values
$fooList : 10px, 20px, 30px, 0px, 200px, 80px, -10px;
#for $i from 1 through length($fooList) {
li:nth-child(#{$i}) {
left: nth($fooList, $i);
}
}
Compiles to:
li:nth-child(1) {
left: 10px;
}
li:nth-child(2) {
left: 20px;
}
li:nth-child(3) {
left: 30px;
}
li:nth-child(4) {
left: 0px;
}
li:nth-child(5) {
left: 200px;
}
li:nth-child(6) {
left: 80px;
}
li:nth-child(7) {
left: -10px;
}

How to fix fullscreen #keyframes loader

On my website, I'm trying to make a simple white full-screen loader with one <div> element, but instead of going to the right at the end, the <div> element goes partially to the left, then snaps to the right. Any ideas on how to fix this? Here's a demo:
body {
background-color: #121212;
}
div#l {
position: absolute;
height: 100%;
top: 0;
background-color: white;
animation: loader 2s infinite;
}
#keyframes loader {
from {
left: 0;
width: 0;
}
49% {
width: 100%;
left: 0;
}
51% {
width: 100%;
right: 0;
}
to {
width: 0;
right: 0;
}
}
<div id='l'></div>
You should divide your keyframe in three equal parts.
from to 33%: the white div appear
from 33% to 66%: change the position of the div
from 66% to to: the white div disappear
Edit you keyframe like this:
#keyframes loader {
from {
left: 0;
width: 0;
}
33% {
width: 100%;
left: 0;
}
66% {
width: 100%;
right: 0;
}
to {
right: 0;
width: 0;
}
}
body {
background-color: #121212;
}
div#l {
position: absolute;
height: 100%;
top: 0;
background-color: white;
animation: loader 2s infinite;
}
#keyframes loader {
from {
left: 0;
width: 0;
}
33% {
width: 100%;
left: 0;
}
66% {
width: 100%;
right: 0;
}
to {
right: 0;
width: 0;
}
}
<div id='l'></div>
As you can see in this way the speed of the animation is not linear, and it is not the result we want.
I sugget you to divide the keyframe in two parts:
from to 50%: the white div appear
from 50% to to: the white div move itself to it's max left position
Therefore:
#keyframes loader {
from {
left: 0;
width: 0;
}
50% {
left: 0;
width: 100%;
}
to {
left: 100%;
width: 0;
}
}
body {
background-color: #121212;
}
div#l {
position: absolute;
height: 100%;
top: 0;
background-color: white;
animation: loader 2s infinite;
}
#keyframes loader {
from {
left: 0;
width: 0;
}
50% {
left: 0;
width: 100%;
}
to {
left: 100%;
width: 0;
}
}
<div id='l'></div>

How to choose specific content i want to pass to the mixin?

I have a #mixin call skewed in SASS.
#mixin skewed {
position: relative;
&::before {
content: '';
display: block;
width: 100%;
height: 50px;
position: absolute;
transform: skewY(-2deg);
#content;
}
&::after {
content: '';
display: block;
width: 100%;
height: 50px;
position: absolute;
transform: skewY(-2deg);
#content;
}
}
From above, you can see that there has #content inside "before" and "after".
The below is the "footer" class, how to pass the content to "before" but not "after".
footer {
padding: 2em 0 0;
height: 100px;
background-color: $color-shade;
margin-top: 3.5em;
#include skewed {
background-color: red;
top: -25px;
}
}
You can add a default variable and a conditional.
DEMO
#mixin skewed($doesAfterHaveContent: false) {
position: relative;
&::before {
content: '';
display: block;
width: 100%;
height: 50px;
position: absolute;
transform: skewY(-2deg);
#content;
}
&::after {
content: '';
display: block;
width: 100%;
height: 50px;
position: absolute;
transform: skewY(-2deg);
#if ($doesAfterHaveContent) { #content; }
}
}
.footer {
#include skewed {
color: red;
}
}
.hey {
#include skewed(true) {
color: red;
}
}

SASS - reference parent of parent

I'm trying to keep my code as DRY as possible. Consider this example:
#parent {
position: relative;
#child {
position: absolute;
top: 0;
left: 0;
}
}
Now I want to add a hover effect on the #parent that will alter the #child. I know I can do it like this:
#parent {
position: relative;
#child {
position: absolute;
top: 0;
left: 0;
}
&:hover #child {
transform: scale(1.2, 1.2);
}
}
But I'm not happy with this solution. It isn't completely DRY because #child is declared twice. Another way to do it is like this:
#parent {
position: relative;
}
#child {
position: absolute;
top: 0;
left: 0;
#parent:hover & {
transform: scale(1.2, 1.2);
}
}
This is arguably more semantic, but no more DRY because #parent is declared twice.
Is there a truly DRY way to do this with SASS?
I have minimum of 5 beautiful ways to do it. i will share 1, if you want more i can share more as well.
Using Functions
#mixin onParentHover() {
$rootString: #{&};
$parentIndex: str-index($rootString, " ");
$parent: str_slice($rootString, 0, $parentIndex - 1);
$children: str_slice($rootString, $parentIndex);
#at-root #{$parent}:hover #{$children} {
#content;
}
}
Usage
#parent {
position: relative;
width: 100px;
height: 100px;
#child {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
#include onParentHover {
transform: scale(1.2, 1.2);
}
}
}
The Final output
#parent {
position: relative;
width: 100px;
height: 100px;
}
#parent #child {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
#parent:hover #child {
text-size: 20px;
}

Resources