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.
Related
CSS compiles the following mixin code:
#mixin message ($color, $background-color: lighten ($color, 20%) ) {
color: $color;
background-color: $background-color;
}
.message-danger { #include message(red); }
to this
.message-danger {
color: red;
background-color: lighten red, 20%;
}
Obviously you can see that CSS did not compile the lighten( ) function properly. I tried to change the color to a hex code color but that made no difference. I thought the problem was from my code editor, but when I tried the code on sassmeister it gave me the same result. Please help.
Can you help me to write some code for create sprite template in Less via gulp spritesmith?
I have sprite.template.mustache with Sass functions and mixins:
$icons: (0:0)
{{#items}}
$icons: map-merge($icons,({{name}}: (X: {{px.offset_x}}, Y:{{px.offset_y}}, W: {{px.width}}, H: {{px.height}}, TW: {{px.total_width}}, TH: {{px.total_height}}, IMG: '{{{escaped_image}}}')))
{{/items}}
{{#options.functions}}
// Gets an attribute from the sass map
#function icon-attr($icon, $attr)
$icon: map-get($icons, $icon)
#return map-get($icon, $attr)
#mixin sprite($iconName)
background-image: url(icon-attr($iconName, IMG))
width: icon-attr($iconName, W)
height: icon-attr($iconName, H)
background-position: icon-attr($iconName, X) icon-attr($iconName, Y)
#mixin sprite-position($iconName)
background-position: icon-attr($iconName, X) icon-attr($iconName, Y)
#mixin sprite-retina($iconName)
background-image: url(icon-attr($iconName, IMG))
$width: icon-attr($iconName, W)
$height: icon-attr($iconName, H)
width: $width/2
height: $height/2
$x: icon-attr($iconName, X)
$y: icon-attr($iconName, Y)
background-position: $x/2 $y/2
$tw: icon-attr($iconName, TW)
$th: icon-attr($iconName, TH)
background-size: $tw/2 $th/2
{{/options.functions}}
I have some trouble with rewriting functions: "map-merge" and "map-get" to Less.
I know that there are no such functions in LESS, but I also know that there are own arrays that can be configured.
Here is the result that I got:
{{#items}}
#{{name}}: {{px.offset_x}}, {{px.offset_y}}, {{px.width}}, {{px.height}}, {{px.total_width}}, {{px.total_height}}, '{{{escaped_image}}}';
{{/items}}
// #{{name}} - name of the img.
{{#options.functions}}
.icon-attr(#icon){
#url: extract(#icon, 7);
#width: extract(#icon, 3);
#height: extract(#icon, 4);
#positionX: extract(#icon, 1);
#positionY: extract(#icon, 2);
#total_width: extract(#icon, 5);
#total_height: extract(#icon, 6);
}
{{/options.functions}}
.sprite(#icon){
.icon-attr(#icon);
display: inline-block;
background-image: url(#url);
width: #width;
height: #height;
background-position: #positionX #positionY;
}
.sprite-position(#icon){
.icon-attr(#icon);
background-position: #positionX #positionY;
}
.sprite-retina(#icon){
.icon-attr(#icon);
background-image: url(#url);
#width_retina: #width;
#height_retina: #height;
width: #width_retina/2;
height: #height_retina/2;
#x: #positionX;
#y: #positionY;
background-position: #x/2 #y/2;
#tw: #total_width;
#th: #total_height;
background-size: #tw/2 #th/2;
}
Example of use:
.icon-search {
.sprite(#search);
}
For a complex map-like data structures manipulation see Lists Less plugin.
But for this particular snippet you don't in fact need any complex structures and thus extra plugins/functions. Plain mixins can serve as a map and its functions in this case just perfect.
Minimal illustrative example:
// declare icon map, each item is injected via {{#items}} template:
.icon(foo) {
#x: 11;
#y: 22;
// etc.
}
.icon(bar) {
#x: 33;
#y: 44;
// etc.
}
// using the map:
.sprite-retina(#icon-name) {
// expand icon properties into this scope:
.icon(#icon-name);
// use the propertes:
x: #x;
y: #y;
// etc.
}
We are using Rails+Sprockets+Compass. Compass defines a linear-gradient function, which conflicts with the css function of the same name.
After our scss file does an #import "compass", is there a way to remove Compass's linear-gradient function so that I can insert a raw linear-gradient into css?
I know I can redefine the function, but I still can't figure out how to redefine it so that I can insert a raw linear-gradient. I want to remove the function entirely.
The problem is that we're migrating to libsass, which means that Compass's Ruby-based functions no longer work. So this
#import "compass";
.tmp {
button-background: linear-gradient(to bottom, #fdefd4, #fdc154);
}
which I would like to be output as-is, compiles to this:
.tmp {
button-background: _linear-gradient_legacy(compact(to bottom), #fdefd4, #fdc154...);
}
where _linear-gradient_legacy is a Ruby-based compass function that will no longer be expanded under libsass.
Compass expects you to use the provided background and background-image functions whenever you use either of the gradient functions (linear/radial). This is how you get your prefixes. The reason why the functions involved are written in Ruby is so that you can get an SVG gradient for browsers that don't support gradients.
If you want absolutely none of that, just redefine the function like so:
#function linear-gradient($options...) {
#return #{'linear-gradient(#{$options})'};
}
Before redeclaring the function:
#import "compass/css3";
.foo {
background: linear-gradient(to bottom, #fdefd4, #fdc154);
}
.bar {
#include background(linear-gradient(to bottom, #fdefd4, #fdc154));
}
Output:
.foo {
background: linear-gradient(to bottom, #fdefd4, #fdc154);
}
.bar {
background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ZkZWZkNCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2ZkYzE1NCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #fdefd4), color-stop(100%, #fdc154));
background: -moz-linear-gradient(top, #fdefd4, #fdc154);
background: -webkit-linear-gradient(top, #fdefd4, #fdc154);
background: linear-gradient(to bottom, #fdefd4, #fdc154);
}
After:
#import "compass/css3";
#function linear-gradient($options...) {
#return #{'linear-gradient(#{$options})'};
}
.foo {
background: linear-gradient(to bottom, #fdefd4, #fdc154);
}
.bar {
#include background(linear-gradient(to bottom, #fdefd4, #fdc154));
}
Output:
.foo {
background: linear-gradient(to bottom, #fdefd4, #fdc154);
}
.bar {
background: linear-gradient(to bottom, #fdefd4, #fdc154);
}
Otherwise, you'll have to implement your own versions of the Ruby functions in Sass.
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;
}
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.