Converting from width to background-width in Less for sprites within CSS class - css

I'm new to advanced CSS and I've been following this tutorial for generating sprites using gruntjs, spritesmith and less. I'm stuck on how to solve the following problem. Firstly, I generate a .less file containing the information of each image inside the sprite. It looks something like this:
#mobile_logout-x: 1586px;
#mobile_logout-y: 0px;
#mobile_logout-offset-x: -1586px;
#mobile_logout-offset-y: 0px;
#mobile_logout-width: 256px;
#mobile_logout-height: 256px;
Using grunt-contrib-less I can now use the following to get the sprite into my target css:
Less template
.mobile_logout {
.sprite(#mobile_logout);
}
Result
.mobile_logout {
background-image: url(images-mobile/mobile-sprite.png);
background-position: -1586px 0px;
width: 256px;
height: 256px;
}
This would be fine if I wanted to use this directly in the HTML, but I'd like to specify this as part of another CSS class. An example would be:
.myTestButton {
background-image: url(images-mobile/mobile-sprite.png);
background-position: -1586px 0px;
width: 256px;
height: 256px;
color: white;
background-size: 1.3em 1.3em;
background-position: top right;
}
The problem is at this stage I can't find a way to get the width and height to be represented as background-width and background-height, which is where I am looking to get to.
I've tried changing the values in the sprite.less file to match what I'm looking for, but have found that was a hack that didn't work. Another option I have been considering is having a mixin to return the correct item with the width translated, but because these are generated from less I couldn't get that to fly either.

Just after posting this I looked into where the sprite function came from and found my answer in the generated sprite.less file:
.sprite-width(#sprite) {
width: ~`"#{sprite}".split(', ')[4]`;
}
.sprite-height(#sprite) {
height: ~`"#{sprite}".split(', ')[5]`;
}
The sprite.less file is generated using a mustache template. In order to solve my problem in Spritesmith you can specify a mustache template. It was also incorrect that I was looking at background-width and the property I needed was background-size. My attempts at inlining also failed, and I should have been looking at using a div rather than sizing the sprite component.

Related

Is it possible to create a Sass Function for getting attribute from class name

I am using HTML dividers like this
<div class="divider-90"></div>
<div class="divider-180"></div>
and
.divider-90 {
height: 90px;
width: 100%;
}
.divider-180 {
height: 180px;
width: 100%;
}
instead of margins on elements.
I want to create a function that generates the div height depending on the class name.
Thank you in advance.
Since SASS generates CSS, and with CSS you can't have dynamic class name, SASS won't be able to do it, but you so something like this (i personally don't like this solution):
#for $i from 1 through 1000{
.divider-#{$i} {
height: #{$i}px;
width: 100%;
}
}
I personally don't like this solution because it will blow your CSS file size, and so it will takes a lot longer to be loaded and parsed, so please, consider using some "chunk based" version, something like every 10px instead every 1px
If you really really need this functionality, i think the best solution will be to use some JS script do generate this height automatically when the page is loaded

Use SVG in pseudo element content or background image in Vue template file

I don't know how I can use a SVG file as a pseudo content element in Vue template files.
In the scoped CSS of my Vue template file (Select.vue) I have:
.wrap {
&:after {
content: url("../../assets/icons/caret-down-solid.svg");
position: absolute;
right: 0;
width: 50px;
height: 50px;
}
}
the path is relative of the components location. But it does not simply show up.
Things I have tried and noticed:
I have tried without the " " around the URL too.
I have tried using a background-image and content: " " instead, didn't work either.
It works with an absolute URL (for example a testfile on the web)
It does resolve the local URL in my example because when I do ../../../asserts/icons/caret-down-solid.svg to take a wrong path it will fail compiling.
So it looks like the file gets resolved, the syntax is correct, but it does not show up for whatever reason.
Edit: When inspecting the pseudo element while using background-image I see:
background-image: url([object Module]);
In case someone comes across this question I managed to solve this.
Problem was that the vue-svg-loader I was using was importing the .svg file as a module. So I had to use an svg-url-loader for importing svgs into styles.
In my vue.config.js under the chainWebpack option I was adding:
config.module.rule("svg")
.oneOf("inline")
.resourceQuery(/inline/)
.use("svg-url-loader")
.loader("svg-url-loader")
.end()
.end()
.oneOf("external")
.use("vue-svg-loader")
.loader("vue-svg-loader");
what this does is when you append a ?inline to your svg it will treat it with a different loader (svg-url-loader in this case)
So in the CSS you do:
.wrap {
&:after {
content: url("../../assets/icons/caret-down-solid.svg?inline");
position: absolute;
right: 0;
width: 50px;
height: 50px;
}
}
and it will import the SVG properly inline.

Override Inline Style

I've read the other questions on here about overriding inline style imported from Javascript and I feel like I'm missing something here.
The iframe and current code can be seen at
https://www.timedoutescape.com/waiver/
(you can put random first / last name and email to get to the signing interface I'm trying to style)
The current code is --
<div id="signingSpace" style="background-color: white; height: 300px; width: 819px;" class="kbw-signature"><canvas width="815" height="296">Your browser doesn't support signing</canvas></div>
And I'm trying to override it with
#signingSpace[style] {
height: 100px !important;
}
Any advice?

Less Variables on left side

I admit I am fairly new to less. While playing with it to make my site as dynamic as possible I was trying to use less variables so if I had to change something I could just do it in one file.
I have run across an issue though when trying to position elements. For example I have a button that is currently sitting on the left side, but in the future I may want to move it to the right. Normally how you call that is either left:0; or right:0;
Is there a way to make that left, or right a variable?
My css looks like this
.previous{
position:fixed;
left:0; //The left is what I want to declare somewhere else
top:#header-padding;
height:#side-height;
font-size: #button-side-font !important;
}
I have tried something like
#{prevPos}: left;
and then calling
#prevPos: 0;
but it just stopped loading my application altogether.
Mixins (update)
Have you tried using a mixin?
It could look something like this:
.previous {
.previous-position();
font-size: #button-side-font !important;
height: #side-height;
position: fixed;
top: #header-padding;
}
.previous-position() {
left: 0;
// right: 0;
}
To swap the left and right, change the comment in the mixin.
Multiple classes approach (original answer)
I'd actually approach this differently. Instead of having the button styles and positioning in the same CSS rule, I'd have the positioning in a sub-class.
.previous {
font-size: #button-side-font !important;
height: #side-height;
}
.previous-left,
.previous-right {
position: fixed;
top: #header-padding;
}
.previous-left {
left: 0;
}
.previous-right {
right: 0;
}
Then your buttons look like this:
I am on the left
I am on the right
I am not fixed
This way you can update your page pretty quickly without having to tear apart your LESS files and it makes your styles more re-usable.
And yet another answer for how to get it to work in a "variable way" using old-fashioned method (intentionally using the most conservative syntax so it could work even with ancient compilers):
#previous-position: right;
.previous {
position: fixed;
margin: 1em;
font-size: 400%;
.-(left) {left: 0}
.-(right) {right: 0}
.-(#previous-position);
}

In CSS or SASS, is using "#foo #bar { width: 200px }" not recommended for increased file size?

Short question is: is the following (an id under another id) not recommended for bloating up the CSS file size?
#product-box #product-photo { width: 200px }
details:
Sometimes in SASS, we might have
#product-box
margin-top: 20px
#product-photo
width: 200px
this way, it means it is "nested" -- that is, #product-photo's style of width 200px is only true within #product-box, and the CSS generated from the SASS is
#product-box { margin-top: 20px }
#product-box #product-photo { width: 200px }
but here we have a redundant #product-box before #product-photo, because #product-photo by itself can uniquely identify the element already.
As a result, the CSS file can become bloated. I wonder if it is recommended to un-indent #product-photo in the SASS file, so that it doesn't need to be nested?
I think we could have a .photo class inside #product-box instead... is it true? But in some cases, we might have 2 photos, or 2 li inside a #product-box, and so using a class cannot uniquely identify an element. If we use jQuery, it is true we can say $('#product-box li:eq(2) to get to any element, but it may introduce bug if somebody add another li without knowing the jQuery code depends on it. Having an id will prevent such bug from happening.
if you're selecting an element by its id, you don't need to have a nested selector - the id has to be uique everytime. if you have a class that has a different style depending on it's parent, you have to use such a nestes selector (but, if a class has the same style in every case, you can drop the parent-selector, too).
example:
#product-box #product-photo { width: 200px }
is the same as
#product-photo { width: 200px }
you could also use a class for that:
.photo { width: 200px }
but: if a photo has a different size in some cases, you have to do something like this:
#product-box .photo { width: 200px }
#another-box .photo { width: 150px }
or, alternatively, define a "default" and a special case:
.photo { width: 200px } // the default
#another-box .photo { width: 150px } // special size for photos inside #another-box
note: i have no idea how to do this in sass (i have no idea what sass is), but i hope this is helping you anyway.
note2: you shouldn't worry about this small effect on the css file-size until you have realy, realy, realy much traffic on your site - it's much more important that everything is readable and easy to understand, otherwise you will get in hell if you have to change something in the future (also, if you wan't to decrease you filesize as much as possible, why do you use such long ids? for breaking that down, wouldn't it be the best to use #a #b #c #d... and so on?)

Resources