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

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

Related

::-webkit-scrollbar is it possible to make the scrollbar-thumb grow instead moving?

I would like my scroll to work like this when the user scrolls. e.g to start to fill up instead of moving.
Is it possible to make the scroll-thumb grow or to style the scrollbar-track-piece different before and after the thumb?
Here is a small example how to implement this loader
window.addEventListener("scroll", (e) => {
var html = document.documentElement;
let step = 100 / (html.scrollHeight - window.innerHeight);
let loader = document.getElementById("scrollprogress");
loader.style.width = (step * html.scrollTop) + "%";
})
#scrollprogress {
height: 5px;
position: fixed;
left: 0;
top: 0;
background: orange;
}
.backgr {
position: fixed;
left: 0;
top: 0;
width: 100vw;
height: 5px;
background: lightgrey;
z-index: -1;
}
.box {
height: 3000px;
}
<div id="scrollprogress"></div>
<div class="backgr"></div>
<div class="box"></div>
You can approximate this using negative box shadow:
body::-webkit-scrollbar {
width: 1em;
}
body::-webkit-scrollbar-thumb {
background-color: orange;
box-shadow:-1000vmax -1000vmax 0px 1000vmax orange;
}
body {
width:300vw;
height:300vh;
background:linear-gradient(60deg,red,blue,orange);
margin:0;
}
html {
background:#fff;
}

dynamically add top in 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);
}

how to change less property by using different param?

I often use similarity less , for example:
.position{
position:absolute;
right:10px;
top:20px;
}
So I want to use a mixin :
.position(#absolute:absolute;#top:0;#right:0;#bottom:0;#left:0){
position: #absolute;
top:#top;
right: #right;
bottom:#bottom;
left:#left;
}
But sometimes I don't need right, but the function always inject right into my code.
So what I should do if I want to have the follow code:
.position(#absolute:absolute;#top:12px;#left:12px;#bottom:12px);
//without 'right'
.position{
position: absolute;
top:12px;
bottom:12px;
left:12px;
}
Thanks!
You can rewrite your mixin like this (it doesn't have any required parameters):
.position(
#position: absolute;
#top: false;
#right: false;
#bottom: false;
#left: false
){
position: #position;
& when not (#top = false) {
top: #top;
}
& when not (#right = false) {
right: #right;
}
& when not (#bottom = false) {
bottom: #bottom;
}
& when not (#left = false) {
left: #left;
}
}
Now you can set only those params you really need:
a {
.position(
#top: 20px,
#left: 0px
);
}
b {
.position(
#bottom: -50px,
#right: 0
);
}
Css output:
a {
position: absolute;
top: 20px;
left: 0px;
}
b {
position: absolute;
right: 0;
bottom: -50px;
}

978.gs is cutting of part of the header

I am using the 978.gs system in a site that I am creating but it is inserting a small band at the top of the page moving the content down slightly. I don't want this to happen.
The site in question is Located Here look at the top of the page.
and my CSS code is
/* Initiate 978.gs */
div.layout-978 { width: 978px; margin: 0px auto; }
div.row { height: 1%; }
div.row-end { clear: both; font: 1px/1px sans-serif; height: 1px; overflow: hidden; }
div.col1, div.col2, div.col3, div.col4, div.col5, div.col6, div.col7, div.col8, div.col9, div.col10, div.col11, div.col12 { float: left; margin-left: 30px; }
div.col1:first-child, div.col2:first-child, div.col3:first-child, div.col4:first-child, div.col5:first-child, div.col6:first-child, div.col7:first-child, div.col8:first-child, div.col9:first-child, div.col10:first-child, div.col11:first-child, div.col12:first-child { margin-left: 0px; }
div.col1 { width: 54px; }
div.col2 { width: 138px; }
div.col3 { width: 222px; }
div.col4 { width: 306px; }
div.col5 { width: 390px; }
div.col6 { width: 474px; }
div.col7 { width: 558px; }
div.col8 { width: 642px; }
div.col9 { width: 726px; }
div.col10 { width: 810px; }
div.col11 { width: 894px; }
div.col12 { width: 978px; }
/* Main CSS */
body{
background: url('img/bg-texture.jpg');
position:relative;
}
Solution:
To fix this problem I edited the following css entry
body{
background: url('img/bg-texture.jpg');
position:relative;
margin-top:0px;
}

CSS - Can't get overflow:hidden to work when overflowing on right or bottom

I have created a template that contains a panel and a content. Depending on the template's class (Top, Left, Right, or Bottom) the panel will have a different position. The expand and collapse animations are performed using transition and classes.
EDIT:
Here is a fiddle: http://jsfiddle.net/ckkVx/2/
/EDIT
Here is the HTML code:
<!DOCTYPE html>
<html>
<head>
<link href="../Css/reset.dev.css" type="text/css" rel="stylesheet">
<link href="../Css/V_PanelTemplate.dev.css" type="text/css" rel="stylesheet">
<script src="../Js/jquery-1.9.1.min.js" type="text/javascript">
<script src="../Js/V_PanelTemplate.dev.js" type="text/javascript">
</head>
<body class="PanelTemplate Bottom">
<div class="Panel AutoHide Collapsed">PANEL</div>
<div class="Content Expanded">CONTENT</div>
</body>
</html>
And here is the CSS code:
#CHARSET "UTF-8";
.PanelTemplate {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
}
.PanelTemplate > .Panel,
.PanelTemplate > .Content {
position: absolute;
-webkit-transition: ease-in-out 400ms;
-moz-transition: ease-in-out 400ms;
-ms-transition: ease-in-out 400ms;
-o-transition: ease-in-out 400ms;
transition: ease-in-out 400ms;
}
.PanelTemplate.Top > .Panel,
.PanelTemplate.Bottom > .Panel {
height: 100px;
left: 0;
right: 0;
}
.PanelTemplate.Left > .Panel,
.PanelTemplate.Right > .Panel {
width: 200px;
top: 0;
bottom: 0;
}
.PanelTemplate.Top > .Content,
.PanelTemplate.Bottom > .Content {
left: 0;
right: 0;
}
.PanelTemplate.Left > .Content,
.PanelTemplate.Right > .Content {
top: 0;
bottom: 0;
}
.PanelTemplate.Top > .Panel {
top: -90px;
}
.PanelTemplate.Left > .Panel {
left: -190px;
}
.PanelTemplate.Right > .Panel {
right: -190px;
}
.PanelTemplate.Bottom > .Panel {
bottom: -90px;
}
.PanelTemplate.Top > .Panel.Expanded {
top: 0;
}
.PanelTemplate.Left > .Panel.Expanded {
left: 0;
}
.PanelTemplate.Right > .Panel.Expanded {
right: 0;
}
.PanelTemplate.Bottom > .Panel.Expanded {
bottom: 0;
}
.PanelTemplate.Top > .Content {
top: 100px;
bottom: 0;
}
.PanelTemplate.Left > .Content {
left: 200px;
right: 0;
}
.PanelTemplate.Right > .Content {
right: 200px;
left: 0;
}
.PanelTemplate.Bottom > .Content {
bottom: 100px;
top: 0;
}
.PanelTemplate.Top > .Content.Expanded {
top: 10px;
}
.PanelTemplate.Left > .Content.Expanded {
left: 10px;
}
.PanelTemplate.Right > .Content.Expanded {
right: 10px;
}
.PanelTemplate.Bottom > .Content.Expanded {
bottom: 10px;
}
/* Test CSS */
.PanelTemplate > .Panel {
background: #777;
color: #FFF;
}
.PanelTemplate > .Content {
background: #333;
color: #FFF;
}
And, if needed, the JavaScript code:
(function($) {
$(document).ready(function() {
var CLOSE_DELAY = 1000;
var $panel = $('.PanelTemplate > .Panel.AutoHide').first();
$content = $('.PanelTemplate > .Content').first();
$panel.mouseenter(function() {
$panel
.addClass('Expanded')
.removeClass('Collapsed')
.data('isMouseOver', true);
$content
.removeClass('Expanded')
.addClass('Collapsed');
}).mouseleave(function() {
$panel.data('isMouseOver', false);
// Waiting a short time in case the mouse accidently leaves
var timeout = setTimeout(function() {
// If it's no longer over after time out, closing
if( ! $panel.data('isMouseOver')) {
$panel
.removeClass('Expanded')
.addClass('Collapsed');
$content
.addClass('Expanded')
.removeClass('Collapsed');
}
clearTimeout(timeout);
}, CLOSE_DELAY);
});
});
})(jQuery);
When I'm using the classes Top or Left on my template, everything works as intended, but when I use either Right or Bottom, the panel, while moving out of the body, expends the window and causes scroll bars to appear.
I read in another question related to overflow:hidden than it could be due to a relatively positioned element, but I don't have any. I also tried to position the html tag and add overflow:hidden to it too, but it didn't help either.
What can I do to prevent this ?
This should fix your issue-
body {
max-width:100%;
}
The problem is in the CSS. Vector's answer with max-width: 100%; is great, but if that doesn't work then use the !Important override feature. For Example:
.PanelTemplate {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden; !Important
}
That will help override the other rules on overflow!

Resources