SASS - reference parent of parent - css

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;
}

Related

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;
}
}

Given three fixed elements, make them render in a specific order

If I have three divs, each with fixed position. How can I get .inner to appear above the .overlay?
HTML
<div class="container">
<div class="inner">The inner container</div>
</div>
<div class="overlay"></div>
CSS
.container {
position: fixed;
z-index: 1;
background: red;
height: 100px;
width: 100%;
}
.inner {
z-index: 3;
position: fixed;
margin-top: 10px;
width: 100%;
background: yellow;
height: 30px;
}
.overlay {
z-index: 2;
position: fixed;
background: blue;
opacity: 0.5;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
In this JS fiddle, you can see how the "yellow" element renders below the overlay. Is there any change possible while keeping the .container fixed?
http://jsfiddle.net/4ne83oa4/8/
Well, if you must keep the markup as is, you can just play around with some pseudo classes for the .container class.
Markup stays the same, the CSS chages a bit like this: check js fiddle
.container {
position: fixed;
background: red;
height: 100px;
width: 100%;
z-index: 1;
}
.container:after,
.container:before{
content: '';
position: fixed;
}
.container:after{
z-index: -1;
background: red;
height: 100px;
width: 100%;
}
.container:before{
z-index: 1;
background: blue;
opacity: 0.5;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.inner {
position: fixed;
margin-top: 10px;
width: 100%;
background: yellow;
height: 30px;
z-index: 1;
}

Image border around HTML Page in IE7 and up

I'm trying to have a border around the entire HTML page something like a photo frame
there's a solution but it doesnt work for IE7+
anybody have any ideas?
edit 1
thank you for the replies, i think i didnt explain my problem clearly. i've included a sample design
https://dl.dropboxusercontent.com/u/604317/test.jpg
basically it's frame that surrounds the page
edit 2
I've added a fiddlejs which i got from #Sebastian Graz, its almost there but the frame need to fill the content not the only the window
http://jsfiddle.net/xzqDQ/1/
#top, #bottom, #left, #right {
background: url('http://f.cl.ly/items/1P2Q1u0O2P44082N1L3a/Screen%20Shot%202013-07-04%20at%204.25.01%20PM.png');
position: fixed;
}
#left, #right {
top: 0; bottom: 0;
width: 30px;
}
#left { left: 0; }
#right { right: 0; }
#top, #bottom {
left: 0; right: 0;
height: 30px;
}
#top { top: 0; }
#bottom { bottom: 0; }
DEMO:http://jsfiddle.net/umbriel/xzqDQ/
Css:
#top, #bottom, #left, #right {
background: url('http://f.cl.ly/items/1P2Q1u0O2P44082N1L3a/Screen%20Shot%202013-07-04%20at%204.25.01%20PM.png');
position: fixed;
}
#left, #right {
top: 0; bottom: 0;
width: 30px;
}
#left { left: 0; }
#right { right: 0; }
#top, #bottom {
left: 0; right: 0;
height: 30px;
}
#top { top: 0; }
#bottom { bottom: 0; }
body {
border:50px solid orange;
}
Is this what you mean?

Creating a hexagon in CSS, symmetry

I have to create a hexagon and I really want it to be full HTML and CSS. It is almost done, except the fact that it is not fully symmetric. The left corner is not aligned with the right corner.
The current css:
.hexagon.outer {
width: 318px;
height: 452px;
position: relative;
}
.hexagon.outer, .hexagon.outer:before, .hexagon.outer:after {
background-repeat:no-repeat;
background-color: #585858;
}
.hexagon.outer:before, .hexagon.outer:after {
content: "";
position: absolute;
width: 262px;
height: 262px;
top:95px;
-moz-transform: rotate(54.5deg) skew(22.5deg);
-webkit-transform: rotate(54.5deg) skew(22.5deg);
transform: rotate(54.5deg) skew(22.5deg);
}
.hexagon.outer:before {
left: -130px;
}
.hexagon.outer:after {
left: 186px;
}
.hexagon.outer span {
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 55px;
background:#585858;
z-index: 1;
}
.hexagon.inner {
width: 276px;
height: 372px;
position: relative;
margin:0 auto;
top: 40px;
z-index:4;
}
.hexagon.inner, .hexagon.inner:before, .hexagon.inner:after {
background-repeat:no-repeat;
background-color: white;
}
.hexagon.inner:before, .hexagon.inner:after {
content: "";
padding:0;
margin:0;
position: absolute;
width: 215px;
height: 215px;
top:79px;
-moz-transform: rotate(54.5deg) skew(22.5deg);
-webkit-transform: rotate(54.7deg) skew(22.5deg);
transform: rotate(54.7deg) skew(22.5deg);
}
.hexagon.inner:before {
left: -107px;
}
.hexagon.inner:after {
left: 169px;
}
.hexagon.inner span {
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 55px;
background:#585858;
z-index: 1;
}
The HTML:
<div class="hexagon outer">
<div class="hexagon inner">
</div>
</div>
Example: http://jsfiddle.net/jK7sH/
The outer hexagon will have an (background) effect in the end, that is why there are two (inner and outer).
I tried to align them by trial and error, but I don't think that works because the :before and :after rectangles are skewed.
Is it possible to create a symmetric hexagon with just CSS without the use of borders?
Thanks in advance for all information!
hexagone is 8 sides , isn't it ?
you could give a try with background linear-gradient
http://dabblet.com/gist/5767212
hover them to and see how it reacts while width increase.

Resources