Extract body class for use in Scss - sass

I am learning Sass but a bit stuck trying to work something out. I'd like to have a unique background image and header image on different pages. How can I perhaps extract the body class name form the markup and interpret that in scss?
Essentially I require some way to prevent having to do this (which is totally the point of scss right?!)
body.page1 {
background: url(../img/bkg-page1.png) left top repeat-x;
header {
background: url(../img/header-page1.png) center top no-repeat;
height: 320px;
}
}
body.page2 {
background: url(../img/bkg-page2.png) left top repeat-x;
header {
background: url(../img/header-page2.png) center top no-repeat;
height: 320px;
}
}
I realise using variables is the right direction, but not sure how to relay the markup class to the scss.
Any pointers would be most appreciated.

What you're looking for is an #each loop:
#each $class in (page1, page2, page3) {
body.#{$class} {
background: url(../img/bkg-#{$class}.png) left top repeat-x;
header {
background: url(../img/header-#{$class}.png) center top no-repeat;
height: 320px;
}
}
}
This assumes that the class name corresponds to the image name, as indicated in your sample.
body.page1 {
background: url(../img/bkg-page1.png) left top repeat-x;
}
body.page1 header {
background: url(../img/header-page1.png) center top no-repeat;
height: 320px;
}
body.page2 {
background: url(../img/bkg-page2.png) left top repeat-x;
}
body.page2 header {
background: url(../img/header-page2.png) center top no-repeat;
height: 320px;
}
body.page3 {
background: url(../img/bkg-page3.png) left top repeat-x;
}
body.page3 header {
background: url(../img/header-page3.png) center top no-repeat;
height: 320px;
}
You could use a #for loop instead (which eliminates the need for the list of class names) if your class names are always going to have numbers at the end of their name.

Related

sass: how to render different images for mobile only

I am not 100% clear on how to implement images for mobile only view that are different than the ones I have for desktop view
So for example, if I have this image for desktop:
&.card {
.card-image {
#include background-helper('gallery/old-pic.jpg', center, contain, no-repeat);
}
}
which comes from the mixin file where I have this code:
#mixin background-helper($image: false, $position: center, $size: contain, $repeat: no-repeat){
#if $image {
background-image: asset-url($image);
background-repeat: $repeat;
background-size: $size;
background-position: $position;
}
}
Not sure what logic to add that would tell my application to render something other than old-pic.jpg if the user is viewing it on a mobile phone.
It seems you have to use media queries.
for example:
$break-small: 320px;
$break-large: 1200px;
.card-image {
#media screen and (max-width: $break-small) {
#include background-helper('gallery/mobile-pic.jpg', center, contain, no-repeat);
}
#media screen and (min-width: $break-large) {
#include background-helper('gallery/old-pic.jpg', center, contain, no-repeat);
}
}

Represent a three.js GUI button with an icon

I want to communicate a "Go Left" button, in a three.js application, by using a left-arrow icon (instead of just labelling it "left")
Many of the three.js examples use dat.GUI to set up GUI control (e.g. button, slider). In all these examples the buttons show up as rectangular boxes
Is it possible to represent a dat.GUI button with an icon? (or at least place a background image behind the button?)
Otherwise, are there other GUI alternatives that are easy to use with three.js?
EDIT:
I'm having trouble to embed the css code inside javascript.
I added the code below and when I click on the button it displays in the console "BEG setStyle", i.e. the function setStyle() is executed.
But I don't see a change in the color or the background image of the "Nukeem all!" button.
#prisoner849 Can you help me with this?
Thanks
var gui = new dat.GUI(),
var obj = {
add:function()
{
console.log("clicked")
updateTheta();
this.setStyle();
},
setStyle:function()
{
console.log("BEG setStyle")
this.color = "#00ff00";
this.backgroundImage = "url('https://cdn4.iconfinder.com/data/icons/6x16-free-application-icons/16/Radiation.png')";
}
};
gui.add(obj, 'add').name('Nukeem all!');
Thanks.
TheJim01 is right. You can do the trick with CSS.
Here is just a rough concept:
var gui = new dat.GUI();
var obj = {
add: function() {
alert("clicked!")
}
};
gui.add(obj, "add").name("Nuke'em all!");
gui.add(obj, "add").name("I'm Fine!");
gui.add(obj, "add").name("Harmony");
var fourth = gui.add(obj, "add").name("CSS is awesome!");
var fourthStyle = fourth.domElement.previousSibling.style;
fourthStyle.backgroundImage = 'url(https://cdn1.iconfinder.com/data/icons/hawcons/32/700035-icon-77-document-file-css-16.png)';
fourthStyle.backgroundRepeat = 'no-repeat';
fourthStyle.backgroundPosition = 'left';
fourthStyle.backgroundColor = 'white';
fourthStyle.color = 'black';
console.log(fourthStyle);
.function:nth-child(1) .property-name {
background-image: url('https://cdn4.iconfinder.com/data/icons/6x16-free-application-icons/16/Radiation.png');
background-repeat: no-repeat;
background-position: right;
background-color: gray;
color: yellow;
}
.function:nth-child(2) .property-name {
background-image: url('https://cdn4.iconfinder.com/data/icons/6x16-free-application-icons/16/OK.png');
background-repeat: no-repeat;
background-position: center;
background-color: teal;
color: aqua;
}
.function:nth-child(3) .property-name {
background-image: url('https://cdn4.iconfinder.com/data/icons/6x16-free-application-icons/16/In-yang.png');
background-repeat: no-repeat;
background-position: left;
background-color: pink;
color: red;
text-align: right;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.1/dat.gui.min.js"></script>

extend Compass breakpoint mixin to avoid duplicates

I am using Compass mixin to create media queries for retina like in example:
header {
height: $header-image-height;
text-align: center;
position: relative;
#include breakpoint($standard-resolution) {
background:
linear-gradient(
rgba(0, 0, 0, 0.1),
rgba(0, 0, 0, 0.1)
),
url(../../img/dist/xxx.jpg) center center no-repeat;
}
#include breakpoint($retina-resolution) {
background:
linear-gradient(
rgba(0, 0, 0, 0.1),
rgba(0, 0, 0, 0.1)
),
url(../../img/dist/xxx_2x.jpg) center center no-repeat;
background-size: 1176px auto;
}
color: $header-color;
#extend %montserrat-bold;
}
It works well. But if I put the same mixin into another element, I will get duplicated output of #media at the end - one for each element:
#media screen and (max-resolution: 1.9999dppx), screen and (-webkit-max-device-pixel-ratio: 1.9999), screen and (max--moz-device-pixel-ratio: 1.9999), screen and (max-resolution: 191.9904dpi) {
header {
background: linear-gradient(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1)), url(../../img/dist/xxx.jpg) center center no-repeat;
}
}
And the same output for another elements. Is there any way I could somehow make placeholder from this mixin, so all elements would be under the same single #media directive?
I found a good solution to avoid duplicate code on the output.
First of all there is a good tool to manage breakpoints called maps:
$breakpoints: (
'retina':
//here put all your breakpoints
)
Second instead of putting breakpoint inside each target element, it is better to put #include directive to the root and inside it put all your elements with new directive respond to like this (I have created separate file for this):
_retina.scss:
#include respond-to(retina) {
element1 {}
.element2 {}
}
End not duplicated code))) I hope it will help somebody. By the way I have discovered that Compass sucks((( I wont use it anymore.

Updating variables created by lighten/darken functions by modifying the original base color afterwards

I'm currently trying to create a mix-in that will let me build buttons with hover values using the darken and lighten color functions in sass. My code for some reason is spitting out white and black for the background color instead of the hex value of a returned color. Here it is on code pen: http://codepen.io/malikabee/pen/vEQZOv
$btn_color: #fff;
$btn_alpha: 1;
$btn_color_amount: 100%;
$color_funcs: (
'darken': darken($btn_color, $btn_color_amount),
'lighten': lighten($btn_color, $btn_color_amount),
'transparentize': transparentize($btn_color, $btn_alpha)
);
#mixin _btn_color($base_color, $amount, $hover){
background: $base_color;
a:hover,
a:focus{
#each $func_name, $color_func in $color_funcs{
#if($func_name == $hover){
$btn_color: $base_color;
$btn_color_amount: $amount;
background-color: $color_func;
}
}
}
}
.btn{
display: inline-block;
vertical-align: bottom;
text-align: center;
border-radius: 10px;
text-decoration: none;
}
.btn_blue{
#include _btn_color(#3c3c3c, 10%, 'darken');
}
Once you get past this block of code, the expressions don't exist anymore, only the value they evaluated to does:
$color_funcs: (
'darken': darken($btn_color, $btn_color_amount),
'lighten': lighten($btn_color, $btn_color_amount),
'transparentize': transparentize($btn_color, $btn_alpha)
);
Changing $btn_color after this point does nothing. Sass cannot to go back in time and re-run those expressions because they've already been evaluated using the original color (black).
What you can do instead is use the call function.
#mixin _btn_color($base_color, $amount, $func){
background: $base_color;
a:hover,
a:focus{
background-color: call($func, $base_color, $amount);
}
}
.btn_blue{
#include _btn_color(blue, 10%, 'darken');
color: white;
}

CSS3 Animation Question

How can I make a CSS3 Animation play to the end and then stop dead. I don't want it to return the elements being transformed back to their initial states.
Right now I'm using some javascript to add a class to the element after the animation's duration with the same properties as 100% in the animation.
This is possible with the "animation-fill-mode" defined as "forwards", at least in Webkit. I got this result with code like this:
#-webkit-keyframes test {
100% { background-color: #0000ff; }
}
a { background-color: #ff0000; }
a:hover { -webkit-animation: test 1s 1 ease forwards }
Note that specifying start color in 0% keyframe and end color in :hover was not necessary.
Of course, this code is Webkit specific. I haven't tried in other browsers with other vendor prefixes or with the general "animation" property.
put your end values in the main css class and the start values in the animation keyframes at 0%:
#keyframes test {
0% {
background-color: #ff0000; /* start value */
}
100% {
background-color: #0000ff;
}
}
a {
background-color: #ff0000; /* normal state */
}
a:hover {
animation-name: test;
animation-duration: 1s;
background-color: #ff0000; /* final state, after animation is finished */
}
In case this question is still open, I don't think this is possible using CSS3 animations as they're currently specified:
An animation does not affect the computed value before the application of the animation, before the animation delay has expired, and after the end of the animation.
However, you should be able to use CSS3 transitions for basic effects. There's a slide in the html5rocks.com presentation that shows how to do this. Here's the relevant [paraphrased] excerpt:
#box.left { margin-left: 0; }
#box.right { margin-left: 1000px; }
#box { -webkit-transition: margin-left 1s ease-in-out; }
// Run this to animate to the left
document.getElementById('box').className = 'left';
// Run this to animate to the right
document.getElementById('box').className = 'right';
animation-fill-mode: forwards
The animation-fill-mode CSS property specifies how a CSS animation should apply styles to its target before and after it is executing

Resources