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;
}
Related
I am working with a Bolts theme in Wordpress. There is a Heroes widget for the main page with 3 "columns". I want to have a different picture for each element and then a different image yet again on the :hover effect.
The 3 static image appear as they should. However, the hover images only show the third selector's declaration to show image 135-3.jpg.
How do I get the first 2 images to be the hover images instead of the third image appearing in all three boxes?
.hero-columns__item {
background-image: url('http://newsite.com/wp-content/uploads/2019/02/MainPageBannersResidential.jpg');
}
.hero-columns__item:hover {
background-image: url('http://newsite.com/wp-content/uploads/2016/04/171-5.jpg') !important ;
}
.hero-columns__item {
background-image: url('http://newsite.com/wp-content/uploads/2019/02/MainPageBannersTerraceHousing2.jpg');
}
.hero-columns__item:hover {
background-image: url('http://newsite.com/wp-content/uploads/2016/04/177-5.jpg') !important;
}
.hero-columns__item {
background-image: url('http://newsite.com/wp-content/uploads/2019/02/MainPageBannersDevelopments.jpg');
}
.hero-columns__item:hover {
background-image: url('http://newsite.com/wp-content/uploads/2016/04/135-3.jpg') !important;
}
The problem is that the selector .hero-columns__item targets all three elements, and when you specify the background-image in the final .hero-columns__item:hover selector, it overwrites the background-image set by the previous two. Thus, the final background-image you set will be applied to all three elements.
To correct this, you'll need selectors that specifically target only the first, second and third elements respectively. This can be done by making use of the pseudo-selector nth-of-type:
.hero-columns__item:nth-of-type(1) {
background-image: url('http://newsite.com/wp-content/uploads/2019/02/MainPageBannersResidential.jpg');
}
.hero-columns__item:nth-of-type(1):hover {
background-image: url('http://newsite.com/wp-content/uploads/2016/04/171-5.jpg');
}
.hero-columns__item:nth-of-type(2) {
background-image: url('http://newsite.com/wp-content/uploads/2019/02/MainPageBannersTerraceHousing2.jpg');
}
.hero-columns__item:nth-of-type(3):hover {
background-image: url('http://newsite.com/wp-content/uploads/2016/04/177-5.jpg');
}
.hero-columns__item:nth-of-type(3) {
background-image: url('http://newsite.com/wp-content/uploads/2019/02/MainPageBannersDevelopments.jpg');
}
.hero-columns__item:nth-of-type(3):hover {
background-image: url('http://newsite.com/wp-content/uploads/2016/04/135-3.jpg');
}
Here, each element has a different selector, so only one of the rules will be applied to each. Note that :hover can still be chained to the pseudo-selector, as is shown above.
Also, don't use !important; it carries maximum specificity, and should be avoided unless absolutely necessary. I've removed their usages in my code above.
Is it possible in Less to create a mixin that can target the backgroubd opacity of an element that already has its background colour set by an existing rule?
E.g
div {
background-colour: red;
}
.opacity {
background-color: fade(#existing-bg, 50%)
}
If I understand you correctly, then not in the sense that you are trying to do - #existing-bg would need to be able to assess the current BG colour at RUNTIME but essentially, we use LESS at compile time. The answer would be to put the colour (red) in a variable and supply the same variable in both places.
#existing: #ff0000;
div {
background-colour: #existing;
}
.opacity {
background-color: fade(#existing, 50%)
}
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);
}
I've got the following mixin that adjusts the width and padding of an item to cope with IE7's lack of support for box-sizing:border-box. It gives me a syntax on & .width(#width: 100, #paddinglr: 0)
I appreciate this is missing a % but any ideas why it's breaking?
.width(#width: 100, #paddinglr: 0) {
width: #width;
padding: #paddinglr;
}
body {
&.lt-ie8 {
& .width(#width: 100, #paddinglr: 0) {
width: #width-#paddinglr;
padding: #paddinglr;
}
}
}
You cannot define a mixin as a selector string, so & .width() for your nested portion cannot be a mixin definition (which is what you have tried to make it).
I think what you are trying to do is make a generic .width() mixin to use on any particular element. It appears that you intend to just set a single number for padding, which is fine.
However, it also appears that (based off your % comment), that you expect this code to produce a width value that is 100% of the parent minus the value of the padding. This is okay, too, assuming you are using percentages for padding also. If you are not, but intend instead that the padding be a pixel value, that mixed units cannot be done by LESS as you might expect, as LESS is a preprocessor, so it is not dynamic in the sense of being able to detect the width of the parent based off the percent at run time and then subtract the padding pixel value.
Now, if your intentions are percentages, or any equal measurement values for both width and padding (whether both px, both em units, etc.), then you can get what you desire by various means. One of the many solutions would be by overriding the .width() mixin within the .lt-ie8 nest, so for example:
.width(#width: 100%, #paddinglr: 0) {
width: #width;
padding: #paddinglr;
}
body {
.someDiv {
.width(100%, 10%);
}
&.lt-ie8 {
/* here is the override of the mixin */
.width(#width: 100%, #paddinglr: 0) {
/* note, I believe you will want to multiply the padding by 2 for the width change due to left and right padding */
width: #width - (2 * #paddinglr);
padding: #paddinglr;
}
/* and here is the override of the actual css */
.someDiv {
.width(100%, 10%);
}
}
}
Which produces this CSS (minus the comments above which were just to communicate to you):
body .someDiv {
width: 100%;
padding: 10%;
}
body.lt-ie8 .someDiv {
width: 80%;
padding: 10%;
}
I'm building form with images like a label...
I have:
DIV.icon-phone {
width: 22px
height: 22px
background: url('icon-set.png') no-repeat 22px 66px;
}
INPUT.pool-phone {
border:1px solid #666;
}
I would something like this:
if INPUT.pool-phone:focus change DIV.icon-phone background-position to: 44px 66px
Please help.
In order to alter some css property of an element when another element is modified, you need to have specific structures..
For your example, the input element must share the same immediate parent as the div and also be before it in the hierarchy.
In this case you can use the ~ General sibling combinator to target it
.pool-phone:focus ~ .icon-phone{
background-position:...
}
Demo at http://jsfiddle.net/gaby/fx5Uy/
otherwise you can use javascript and bind to the onfocus event..
you could write a javascript function to take care of that for you.
[the input button].onfocus = function changeBg () { [thediv].style.background="[whatever you want]" };
[the input button].onblur = function resetBg () { [thediv].style.background="[whatever you want]" };
Gaby posted a pure css version which is preferable (at least to me).