I'm fairly new to LESS, and I have some code--which seems to work--for a sprite given to me that looks like this. First a variable is defined as follows:
#my_img: 0px 105px 0px -105px 22px 22px 44px 150px 'sprites/sprite-img.png';
This variable gets used like this:
.someClass {
.sprite(#my_img);
}
CSS output of this looks like this:
.someClass{
background-image: url("sprites/sprite-img.png");
background-position: 0 -105px;
height: 22px;
width: 22px;
}
What do the parameters in that variable definition indicate? The last one (url) is obvious, and I believe from looking at the sprite that the 3rd and 4th ones seem to be the background position offsets (X and Y). But what are the others? What do each of the 9 elements in this variable specify?
?
?
horizontal position
vertical position
width
height
?
?
background-image url
The comments on other answers helped make it clear that the .sprite usage is actually not part of LESS, but is a mixin definition, as follows. So the extra stuff in the variable definition is not used in the sprite at all, but exists for other uses.
.sprite-width(#sprite) {
width: ~`"#{sprite}".split(', ')[4]`;
}
.sprite-height(#sprite) {
height: ~`"#{sprite}".split(', ')[5]`;
}
.sprite-position(#sprite) {
#sprite-offset-x: ~`"#{sprite}".split(', ')[2]`;
#sprite-offset-y: ~`"#{sprite}".split(', ')[3]`;
background-position: #sprite-offset-x #sprite-offset-y;
}
.sprite-image(#sprite) {
#sprite-image: ~`"#{sprite}".split(', ')[8].slice(1, -2)`;
background-image: url(#sprite-image);
}
.sprite(#sprite) {
.sprite-image(#sprite);
.sprite-position(#sprite);
.sprite-width(#sprite);
.sprite-height(#sprite);
}
Related
I'm building a reusable, customizable component. The component has several configuration options, each option has several values to choose from.
Consider these two options for example:
content-position: left, right, top, bottom, center,
content-padding: small, medium, large.
The tricky part is that the padding must be different depending on the position. E. g. when content position is left, then the left padding must be enlarged and the right padding must be reduced.
It's pretty trivial to achieve with HTML classes:
<MyComponent class="--content-position-left --content-padding-small"/>
.MyComponent__Content {
.MyComponent.--content-padding-small & {
padding: 50px;
}
.MyComponent.--content-padding-small.--content-position-left & {
padding-left: 75px;
padding-right: 25px
}
.MyComponent.--content-padding-medium & {
padding: 100px;
}
.MyComponent.--content-padding-medium.--content-position-left & {
padding-left: 150px;
padding-right: 50px;
}
}
This works perfectly when you are OK with applying configuration via HTML.
But I want to provide a way of configuring this component with pure Sass, without applying HTML classes.
It should be possible to do something like this:
.Page__Products {
.MyComponent {
#include my-component--content-position("left");
#include my-component--content-padding("small");
}
}
How can I make the my-component--content-padding know which padding side should be larger, if any?
I see two obvious solutions:
Merge two mixins into one, and make it accept two arguments, something like:
#include my-component--content-position-and-padding("small", "left");
I don't like this approach. It gets really messy when there are multiple options depending on each other.
Instead of multiple single-purpose mixins, you end up with a single "god" mixin to control everything.
Keep mixins separate, but make each mixin accept all the information it needs:
#include my-component--content-position("left");
#include my-component--content-padding("small", "left");
This is better, but I don't like the redundancy: you have to specify "left" twice.
So I wonder if I could do the following, and the padding mixin would know how exactly to distort padding depending on which position has been applied by the other mixin:
.Page__Products {
.MyComponent {
#include my-component--content-position("left");
#include my-component--content-padding("small");
}
}
This would be trivial to do with a real programming language, but Sass seems to fall short?
PS I don't want mixins to depend on the order they have been applied in and on global variables.
constants:
$none: none;
$left: left;
$right: right;
$mediumPadding: 100px;
$mediumPaddingLeft: 100px 50px 100px 150px;
$mediumPaddingRight: 100px 150px 100px 50px;
$smallPadding: 50px;
$smallPaddingLeft: 50px 25px 50px 75px;
$smallPaddingRight: 50px 75px 50px 25px;
Mixins:
#mixin align-padding($align, $padding)
{
float: $align;
padding: $padding;
}
SCSS:
.what-you-want-to-hang-it-on
{
#include align-padding($none, $mediumpadding);
}
I created a mixin to manipulate easily images and replace, now my app it is growing and I don't know how to improve this code.
basically I have a include: #include img-replace("logo.png", 104px, 47px, inline-block); where I simple change the name of the image and define the pixels width and height.
I would like change it because now, some developers want just change that image name and not worry about the size anymore understand?
in that case the image has: width: 104px and height:47px, so they would like not to worry about it anymore since the next image can be bigger or smaller.
so guys any solution for this? thank you.
$path--rel : "../images";
#mixin img-replace($img, $w, $h, $disp: block) {
background-image: url('#{$path--rel}/#{$img}');
background-repeat: no-repeat;
width: $w;
height: $h;
display: $disp;
}
.site-logo {
#include img-replace("logo.png", 104px, 47px, inline-block);
margin-top: 8px;
margin-left: 6px;
}
Using SASS, you are able to set default values against parameters in a mixin; in your example for instance, I have specified the width to be 104px by default and the height to be 47px by default:
$path--rel: "../images";
#mixin img-replace($img, $w:104px, $h:47px, $disp:null) {
background-image: url('#{$path--rel}/#{$img}');
background-repeat: no-repeat;
width: $w;
height: $h;
#if ($disp) {display: $disp;}
}
.site-logo {
#include img-replace(
$img: "logo.png",
$disp: "inline-block"
);
margin-top: 8px;
margin-left: 6px;
}
If $w,$h or $disp are left off the default values get rendered. This essentially makes them optional.
The problem is that if you make the sizes optional, the element will have no width or height. This means the dev will still have to determine the elements' size or else it will just be 0x0 and the picture won't show!
If the problem is that the dev is too lazy to find and write the size of the images, you could always use a map to store all images and their sizes, so the function would insert the correct sizing depending on the image value. Read more here
So if i understand correctly, you want to use this mixin, by just passing the image path. But each image has a different size.
This cannot be done with SASS.
Instead, you should add your image inline, eg:
<img src="images/logo.png" alt="">
or
<img src="images/logo.png" alt="" width="104" height="74">
Otherwise the answer by #chris-spittles above is correct, meaning that you should pass the default width and height to your mixin.
And if you want to continue using the mixin you will need to pass the width and height for the images that have different dimensions.
As suggested before if you change your mixin to this -
#mixin img-replace($img, $w: null, $h: null, $disp: block) {
background-image: url('#{$path--rel}/#{$img}');
background-repeat: no-repeat;
display: $disp;
width: $w;
height: $h;
}
You can use your code flexibly without having any need to assign width and height arguments. So, now, if you write this -
.site-logo {
#include img-replace("logo.png");
margin-top: 8px;
margin-left: 6px;
}
it will get compiled to -
.site-logo {
background-image: url("../images/logo.png");
background-repeat: no-repeat;
display: block;
margin-top: 8px;
margin-left: 6px;
}
It will also preserve your previously written codes, without any changes.
Now, if you have any specific requirements, like providing default values to different types of images which a developer can assign, you can add maps in your code -
$small-img: ( w: 100px, h: 100px );
$medium-img: ( w: 200px, h: 200px );
Now you can call img-replace like this -
.site-logo {
#include img-replace("logo.png", $small-img...);
}
.site-medium-image {
#include img-replace("logo.png", $medium-img...);
}
This will get compiled to -
.site-logo {
background-image: url("../images/logo.png");
background-repeat: no-repeat;
display: block;
width: 100px;
height: 100px;
}
.site-medium-image {
background-image: url("../images/logo.png");
background-repeat: no-repeat;
display: block;
width: 200px;
height: 200px;
}
This ... makes arguments variable arguments
Sass supports "variable arguments," which are arguments at the end of
a mixin or function declaration that take all leftover arguments and
package them up as a list. These arguments look just like normal
arguments, but are followed by ...
I'm in the midst of creating a SASS mixin that will let me take a spritesheet of social media icons and display them, but I'm having an issue with the background-position when it's hovered over, here's the SASS code:
#mixin social-button($imgurl,$xpos,$ypos,$height,$width) {
background-image: url($imgurl);
background-position: $xpos $ypos;
display: block;
float: left;
height: $height;
width: $width;
&:hover {
background-position: 0px -$height;
}
& span {
position: absolute;
top: -999em;
}
}
And my include:
a.facebook {
#include social-button("../img/social-buttons.png",0px,0px,26px,26px);
}
If you'd like to see/use the spritesheet in action, I've uploaded it here: http://i49.tinypic.com/2evtbwp.png
Here's the HTML as well:
<a class="facebook" href="#"><span>Facebook</span></a>
Essentially the CSS output for the hover is displaying as this:
a.facebook:hover {
background-position: -26px;
}
And in Firebug it displays as this:
a.facebook:hover {
background-position: -26px center;
}
Any help is greatly appreciated, I'm pretty stumped on what I'm doing wrong at this point.. thanks!
PS. I'm going to be creating 5 of these, so I wouldn't mind creating a loop that could auto generate that for me, but at the present time it's not a huge deal, just need to get the hovers working first!
You have to add parentheses around variables when you change them to negatives otherwise it just does the math (0px - $height):
background-position: 0px (-$height);
You probably want to fix the 0px, too.
I'm using a custom radio button spritesheet for an application that I'm writing for my work. I've split up this spritesheet logically into columns and rows - the columns and rows correspond with specific states that the radio button can have. (The columns are states, such as disabled, and application states, such as "correct" or "incorrect", while the rows are for selected states and hover/focus states.
My implementation uses dynamically-added semantic classes to influence the background position. As such, if a radiobutton is marked "correct" and it has focus, a "correct" CSS class will be applied and a "focus" class will be applied, calling the background position for the column and row respectively.
For these classes, I'm currently using the background-position-x and background-position-y CSS attributes, which work in IE and chrome, but not in Firefox and Opera. (These two properties aren't officially part of any CSS spec.) Since we're using the LESS preprocessor, I want to know if there's a way to create a LESS mixin that will dynamically "inherit" an x or y value for the "background-position" property.
In psuedocode, something like this:
.my-background-mixin-x(#value) {
background-position: #value + 'px', inherit; (inherit y-value)
}
.my-background-mixin-y(#value) {
background-position: inherit, #value + 'px'; (inherit x-value)
}
(That's not really accurate syntax, but I hope it conveys the idea.)
Is this possible in LESS? Can less store variables and target properties like this?
Thanks!
You cannot have LESS inherit values that way, and background-position itself can only inherit both values in the CSS cascade. I think a possible "easy" solution would be the following code. Note: Since I do not know your sprite positioning, for the sake of illustration here, I have assumed the following:
Your columns are 10px wide and are in the order of a) a "base" image, b) your disabled image, c) your .correct image, and d) your .incorrect image.
Your rows are 10px tall and are in the order of a) a "base" image, and b) your hover and .focus image (which are the same in my example; not sure about your real situation).
That your "base" and disabled settings do not require a :hover or .focus value.
Given those assumptions, then using a mixin with a horizontal (X) and vertical (Y) shift amount, with a passed in multiplier for the column and row position in the sprite, can give us this code (which you should be able to modify in such places where my assumptions were wrong):
LESS Code
input[type=radio] {
// bkg position set mixin
.setBkgPos(#X: 0, #Y: 0) {
#Xshift: -10px;
#Yshift: -10px;
background-position: (#Xshift * #X) (#Yshift * #Y);
}
.setBkgPos;
&[disabled="disabled"] {
.setBkgPos(1, 0);
}
&.correct {
.setBkgPos(2, 0);
&:hover, &.focus {
.setBkgPos(2, 1);
}
}
&.incorrect {
.setBkgPos(3, 0);
&:hover, &.focus {
.setBkgPos(3, 1);
}
}
}
CSS Example Output
input[type=radio] {
background-position: 0px 0px;
}
input[type=radio][disabled="disabled"] {
background-position: -10px 0px;
}
input[type=radio].correct {
background-position: -20px 0px;
}
input[type=radio].correct:hover,
input[type=radio].correct.focus {
background-position: -20px -10px;
}
input[type=radio].incorrect {
background-position: -30px 0px;
}
input[type=radio].incorrect:hover,
input[type=radio].incorrect.focus {
background-position: -30px -10px;
}
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Best Way to Sprite Images?
I have the following image that I want to use for users to log into site.
http://dl.dropbox.com/u/7468116/facebook_signin.png
However I am not able to make css work properly.
.sprite {
background-image: url("pathto/facebook_signin.png");
background-position: 0 0;
}
.sprite:hover {
background-position: 0 16px /*or whatever the y position of the 2nd button is*/
}
.sprite:active {
background-position: 0 32px /*or whatever the y position of the 3rd button is*/
}
Something like this should work:
a.fb {
display: block;
background: ("/path/to/sprite.png") 0 0 no-repeat; /* start with normal state */
width: 150px;
height: 18px;
text-indent: -9999px; /* for image replacement */
}
a.fb:hover,
a.fb:focus {
/* hover and focus state */
background-position: 0 -20px;
}
a.fb:active {
/* click state */
background-position: 0 -40px;
}
If you are on mac, you can use some tools for writing your CSS file automatically. These tools are ordering your sprites in an effective way and also writes CSS files for you. You don't need to fight with ordering and calculating pixel coordinates, etc. I
suggest Sprite Master.
What exactly's not working in your CSS? Spriting is involves changing the background position of the image on hover (or other states).
So it's really just
#element {
background-position-y: 10px;
}
#element:hover {
background-position-y: 0px;
}
Would be helpful to see your CSS.