dynamically add top in css? - css

Is there a way to dynamically add top in css/less? I have the following structure:
.a2a-desktop-right {
right: 0px;
.a2a_svg {
position: absolute;
right: 8px;
}
}
.a2a_svg has some animation effects on hover and needs to be absolutely positioned, however there can be n-types of this element. Each one needs a top of 40px more than the previous. Any way to accomplish this without js?
EDIT
I can't define the style inline - it's a 3rd party script that generates these elements. That's also why javascript is out of the question - I won't know when the elements are rendered, and if I did it would still take time for the new styles to be applied.

I managed to find a way to do it with less after seeing the below by edwinnwebb.
/* Define two variables as the loop limits */
#from : 0;
#to : 10;
/* Create a Parametric mixin and add a guard operation */
.loop(#index) when(#index =< #to) {
/* As the mixin is called CSS is outputted */
div:nth-child(#{index}) {
top: unit(#index * 100, px);
}
/* Interation call and operation */
.loop(#index + 1);
}
/* the mixin is called, css outputted and iterations called */
.loop(#from);
/*
## Output
div:nth-child(0) {
top: 0px;
}
div:nth-child(1) {
top: 100px;
}
div:nth-child(2) {
top: 200px;
}
div:nth-child(3) {
top: 300px;
}
div:nth-child(4) {
top: 400px;
}
div:nth-child(5) {
top: 500px;
}
div:nth-child(6) {
top: 600px;
}
div:nth-child(7) {
top: 700px;
}
div:nth-child(8) {
top: 800px;
}
div:nth-child(9) {
top: 900px;
}
div:nth-child(10) {
top: 1000px;
}
*/
Applied to my problem becomes...
#iterations: 0;
.svg-loop (#iterations) when (#iterations =< 5) {
.a2a-button.a2a-desktop-right:nth-of-type(#{iterations}) {
.a2a_svg{
top: unit((#iterations * 40) - 33, px);
}
}
.svg-loop(#iterations + 1);
}

Related

Why is overflow-y required for a CSS parallax effect?

I have created a barebones parallax demo. This works fine, as you can see if you run the snippet below. However, it stops working if I remove the following CSS rule:
main {
overflow-y: auto;
}
Why is it necessary to include a rule for a vertical scrollbar, when there is no need to scroll vertically?
body {
margin: 0;
}
main {
width:100vw;
height:100vh;
perspective: 2px;
/* overflow-y MUST be set to a certain value for parallax to work
* WORKS:
* + auto
* + hidden
* + overlay
* + scroll
* FAILS:
* - clip
* - inherit
* - initial
* - revert
* - unset
* - visible
*/
overflow-y: auto;
}
div {
position: absolute;
top: 0;
width: 99vw;
height: 100%;
}
div:nth-child(1) {
left: 0;
background-color: #900;
}
div:nth-child(2) {
left: 49.5vw;
background: rgba(0,192,0,0.5);
height: 80%;
top: 10%;
transform: translateZ(1px) scale(0.5);
z-index: 1;
}
div:nth-child(3) {
left: 99vw;
background-color: #009;
}
<body>
<main>
<div></div
><div></div
><div></div>
</main>
</body>
Why is it necessary to include a rule for a vertical scrollbar, when there is no need to scroll vertically?
You need to scroll vertically but you need to scroll the main and no the sceen. There is a small trap here because removing the scroll of the main will make the default scroll of the screen to appear and you think both are the same but no. We need to scroll the main because the perspective is defined there.
Reduce the width/height slightly and you will better understand. now if you remove/add overflow you will see that it's different
body {
margin: 0;
}
main {
width: 90vw;
height: 90vh;
perspective: 2px;
overflow-y: auto;
}
div {
position: absolute;
top: 0;
width: 99vw;
height: 100%;
}
div:nth-child(1) {
left: 0;
background-color: #900;
}
div:nth-child(2) {
left: 49.5vw;
background: rgba(0, 192, 0, 0.5);
height: 80%;
top: 10%;
transform: translateZ(1px) scale(0.5);
z-index: 1;
}
div:nth-child(3) {
left: 99vw;
background-color: #009;
}
<main>
<div></div>
<div></div>
<div></div>
</main>
Basically, the element having the perspective need to have its content scrolling to see the effect.

when adding a class, styles are applied without smooth transition

I want an element to get applied some styles in a smooth way after 2 seconds. I tried setTimeout, to add the class after two seconds, but despite having declared transition: all 1s to absolutely everything, when the class (containing new styles )is added, I can't see any "transition", the new styles are just applied without smoothness.
How can I fix it?
var s2 = document.querySelector("#section2");
setTimeout(() => {
s2.classList.add("up");
}, 2000);
html * {
transition: 1s all;
}
body {
overflow: hidden;
}
#section1 {
background: steelblue;
}
#section2 {
background: indigo;
position: absolute;
}
section {
width: 100%;
height: 100vh;
}
.up {
top: 0px;
}
<section id="section1"></section>
<section id="section2"></section>
What I want to achieve is that the div that is below the first one start moving up until it reaches the top of the window, like a "slide-up" effect. Why are "transition" property being ignored after adding the class containing this new styles?
You need to apply an initial value for the top rule to allow the transition to take effect.
var s2 = document.querySelector("#section2");
setTimeout(() => {
s2.classList.add("up");
}, 2000);
html * {
transition: 1s all;
}
body {
overflow: hidden;
position: relative; /** ensure section#section2 is positioned relative to the body **/
}
#section1 {
background: steelblue;
}
#section2 {
background: indigo;
position: absolute;
top: 100vh; /** initial value **/
}
section {
width: 100%;
height: 100vh;
}
/** #section2.up is more specific **/
#section2.up {
top: 0;
}
<section id="section1"></section>
<section id="section2"></section>
You can also animate with an external library like jQuery:
$("#section2").animate({
top: 0,
duration: 2000
});
html * {
transition: 1s all;
}
body {
overflow: hidden;
}
#section1 {
background: steelblue;
}
#section2 {
background: indigo;
position: absolute;
}
section {
width: 100%;
height: 100vh;
}
<script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<section id="section1"></section>
<section id="section2"></section>

SCSS - merging two the same selectors? [duplicate]

I'm trying to contain general styles/tricks in a separate mixin file which can be applied to any project when they're needed. Some of these styles require multiple elements to work together in order to work.
For example:
_mixins.scss
====================
#mixin footer_flush_bottom {
html {
height: 100%;
}
body {
min-height: 100%;
position: relative;
}
#footer {
position: absolute;
bottom: 0;
}
}
main.scss
====================
#import "mixins";
#include footer_flush_bottom;
html {
background-color: $bg;
//More stuff
}
body {
margin: 0 auto;
//More stuff
}
footer.scss
====================
#footer {
height: 40px;
}
As it is, the mixin works but the generated css separates the mixin from the main code, even when their selectors are the same. The downside to this is ugly css and larger file size when I start including more of these.
/* line 14, ../../sass/modules/_mixins.scss */
html {
height: 100%; }
/* line 18, ../../sass/modules/_mixins.scss */
body {
min-height: 100%;
position: relative; }
/* line 22, ../sass/modules/_mixins.scss */
#footer {
position: absolute;
bottom: 0; }
/* line 19, ../../sass/modules/main.scss */
html {
overflow-y: scroll; }
/* line 37, ../../sass/modules/main.scss */
body {
margin: 0 auto;
/* line 1, ../sass/modules/footer.scss */
#footer {
height: 40px;
Is there anyway I can do this so that same selectors can be merged? Like this:
/* line 19, ../../sass/modules/main.scss */
html {
height: 100%;
overflow-y: scroll; }
/* line 37, ../../sass/modules/main.scss */
body {
min-height: 100%;
position: relative;
margin: 0 auto;
/* line 1, ../sass/modules/footer.scss */
#footer {
position: absolute;
bottom: 0;
height: 40px;}
No. Sass has no way of merging selectors (this could be considered undesirable, as it would alter the ordering of the selectors).
The only thing you can really do is something like this (or write 2 separate mixins):
#mixin footer_flush_bottom {
height: 100%;
body {
min-height: 100%;
position: relative;
#content;
}
}
html {
// additional html styles
#include footer_flush_bottom {
// additional body styles
}
}

Use variables inside :nth-child(n + x) pseudo class

At the moment I have a snippet of LESS that will basically shift each subsequent child further down from the top:
&:nth-child(n+2) {
top: #alertTop + 10px;
}
&:nth-child(n+3) {
top: #alertTop + 20px;
}
&:nth-child(n+4) {
top: #alertTop + 30px;
}
Is there anyway to use the 'x' part of 'n+x' in the calculation so that I don't have to manually add these?
I.e. something like:
&:nth-child(n+x) {
top: #alertTop + (x * 5px);
}
LESS/CSS only methods preferred.
From the documentation: Create a mixin that calls itself, along with a guard expression:
LESS
#test {
#child-count: 5;
#child-height: 100px;
position: relative;
height: #child-count * #child-height;
> div {
position: absolute;
left: 0;
right: 0;
height: #child-height;
background: red;
}
.loop(#i) when (#i <=5) {
> :nth-child(#{i}) {
top: (#i - 1) * #child-height;
}
.loop(#i + 1);
}
.loop(1);
}
Result
#test {
position: relative;
height: 500px;
}
#test > div {
position: absolute;
left: 0;
right: 0;
height: 100px;
background: red;
}
#test > :nth-child(1) {
top: 0px;
}
#test > :nth-child(2) {
top: 100px;
}
#test > :nth-child(3) {
top: 200px;
}
#test > :nth-child(4) {
top: 300px;
}
#test > :nth-child(5) {
top: 400px;
}
CodePen

Merging selectors from mixins

I'm trying to contain general styles/tricks in a separate mixin file which can be applied to any project when they're needed. Some of these styles require multiple elements to work together in order to work.
For example:
_mixins.scss
====================
#mixin footer_flush_bottom {
html {
height: 100%;
}
body {
min-height: 100%;
position: relative;
}
#footer {
position: absolute;
bottom: 0;
}
}
main.scss
====================
#import "mixins";
#include footer_flush_bottom;
html {
background-color: $bg;
//More stuff
}
body {
margin: 0 auto;
//More stuff
}
footer.scss
====================
#footer {
height: 40px;
}
As it is, the mixin works but the generated css separates the mixin from the main code, even when their selectors are the same. The downside to this is ugly css and larger file size when I start including more of these.
/* line 14, ../../sass/modules/_mixins.scss */
html {
height: 100%; }
/* line 18, ../../sass/modules/_mixins.scss */
body {
min-height: 100%;
position: relative; }
/* line 22, ../sass/modules/_mixins.scss */
#footer {
position: absolute;
bottom: 0; }
/* line 19, ../../sass/modules/main.scss */
html {
overflow-y: scroll; }
/* line 37, ../../sass/modules/main.scss */
body {
margin: 0 auto;
/* line 1, ../sass/modules/footer.scss */
#footer {
height: 40px;
Is there anyway I can do this so that same selectors can be merged? Like this:
/* line 19, ../../sass/modules/main.scss */
html {
height: 100%;
overflow-y: scroll; }
/* line 37, ../../sass/modules/main.scss */
body {
min-height: 100%;
position: relative;
margin: 0 auto;
/* line 1, ../sass/modules/footer.scss */
#footer {
position: absolute;
bottom: 0;
height: 40px;}
No. Sass has no way of merging selectors (this could be considered undesirable, as it would alter the ordering of the selectors).
The only thing you can really do is something like this (or write 2 separate mixins):
#mixin footer_flush_bottom {
height: 100%;
body {
min-height: 100%;
position: relative;
#content;
}
}
html {
// additional html styles
#include footer_flush_bottom {
// additional body styles
}
}

Resources