Less CSS Set Dynamic Background Image with Mixin

LESS css set dynamic background image with mixin

:) got my answer!

it needs to be used like this in my case :

.bg-img(@img) { background-image:url("@{img}"); }

#logo { .bg-img("../images/logo.jpg"); }

LESS mixin with loop creating background images

Ok the issue is you are over complicating things and missing second parameter. Your code above calls to counter which is NOT a recursive mixin, the inner recursive mixin does not get invoked at any time which is why you never see any generated code. It isn't like lot of other programming languages where it would run the code inside of the function

.counter(@counter, @name) when (@counter > 0) {
.counter((@counter - 1), @name); // next iteration
.cat-wrapper-@{name} .cat-@{counter} {
background-image: url('/mediafiles/@{name}/cat_@{counter}.jpg')
}
}

.counter(2, name);

Recursive mixin .counter(@counter, @name: name) when (@counter > 0)

You need that second parameter and it needs to be optional, since you are not calling it .counter((@counter - 1));

OR

you pass it to the count-1 call which I have done in my above code .counter(@counter, @name) and then again at .counter((@counter - 1), @name);

You don't need the outer mixin, it serves no purpose

You can test this here https://lesstester.com/

Dynamic LESS mixin

So there are basically two parts to this question. The first is how to dynamically interpolate your variable names in your mixin, and the second is how to figure out if the variable you interpolated even exists.

The first part can be done like so:

@body-margin: 50px;

.spacing(@id) {
margin: ~"@{@{id}-margin}";
}

If you do that, then using

body {
.spacing('body);
}

Will give you your expected CSS output of

body {
margin: 50px;
}

Read more about that here: Defining Variable Variables using LESS CSS.

The second part, determining whether the interpolated variable even exists, I don't think you can do in LESS. You are going to have to define all possible variables ahead of time, but that doesn't mean you can't get clever with how you define those variables.

Say you don't want to define a variable for @body-padding-mobile. In that case, you can do one of two things, whichever you think is more helpful for you.

The first is that you could set the variable value equal to whatever the default value is in CSS (0, in the case of padding), or else just initial.

Or, if you're afraid that will mean you end up overwriting styles you don't want to overwrite, the more hacky solution is to just make the variable equal to an invalid value, so the browser never applies the style. For example: @body-padding-mobile: fishsticks.


Assuming you've declared all the variables you need for the mixin, you can use this mixin to get what you want:

.spacing(@id) {
margin: ~"@{@{id}-margin}";
padding: ~"@{@{id}-padding}";
@media (max-width: 900px) {
margin: ~"@{@{id}-margin-tablet}";
padding: ~"@{@{id}-padding-tablet}";
}
@media (max-width: 500px) {
margin: ~"@{@{id}-margin-mobile}";
padding:~"@{@{id}-padding-mobile}";
}
}

So if we start with this:

@body-margin: 50px;
@body-margin-tablet: 30px;
@body-margin-mobile: 20px;

@body-padding: 150px;
@body-padding-tablet: 130px;
@body-padding-mobile: 0;

body {
.spacing('body');
}

We'll get this:

body {
margin: 50px;
padding: 150px;
}
@media (max-width: 900px) {
body {
margin: 30px;
padding: 130px;
}
}
@media (max-width: 500px) {
body {
margin: 20px;
padding: 0;
}
}

LESS: mixin for background position in sprites... implementing background size as well

There are definitely multiple ways of making a bit more interesting mixins. Your example from above could be transformed into LESS code like this, for example:

@origw: 200; // original width

.bgw(@s){
background-size: unit(@origw * @s,px) auto;
} .bgw(1){}

.bg_h_pos(@ind, @width, @background-size: 1){
.bgw(@background-size);
@left: -((@ind - 1) * @width * @background-size);
background-position: unit(@left,px) 0px;
}

Where I made a separate mixin .bgw, that adds the background-size property if the parameter differs from 1, otherwise it does nothing. You could also use guards instead. Hope this gives you some idea.

As of good resources ... I would say the most extensive one is the documentation at lesscss.org that gives you an overview of the functionality. In addition to that, I find looking/flipping/searching through answers here on SO an invaluable source of very good ideas for what all is possible (sometimes you will find examples of pretty smart and exciting solutions to quite complex problems in LESS).

Dynamically define a variable in LESS CSS

This Cannot Be Done

What you desire to do is not currently possible in LESS. I can think of two possible "workarounds" if you know ahead of time what variable names you want to allow to be used (in other words, not fully dynamic). Then something like one of the following could be done:

Idea #1 (Variable Variables)

.define(@var) {
@fooBar: 0;
@fooTwo: 2;
@fooYep: 4;

@fooSet: 'foo@{var}';
}

.define(Two);
.test {
.define(Bar);
prop: @@fooSet;
}
.test2 {
prop: @@fooSet;
}

Idea #2 (Parametric Mixins)

LESS

.define(@var) {
.foo() when (@var = Bar) {
@fooBar: 0;
}
.foo() when (@var = Two) {
@fooTwo: 2;
}
.foo() when (@var = Yep) {
@fooYep: 4;
}
.foo();
}

.define(Two);
.test {
.define(Bar);
prop: @fooBar;
}
.test2 {
prop: @fooTwo;
}

CSS Output (for both ideas)

.test {
prop: 0;
}
.test2 {
prop: 2;
}

Conclusion

But I'm not sure how useful either would really be, nor do I know if it could have any real application in your actual use case (since you mention the above is not the real use case). If you want a fully dynamic variable in LESS, then it cannot be done through LESS itself.

LESS CSS - ID and background para

Would it not be something like this

.definition (@image: nameOfImageDefault) {
background: url('@{imagesUrl}/@{image}') no-repeat;
width: 874px;
height: 188px;
}

li #prize-1 span {
.definition(nameOfImage);
}
li #prize-2 span {
.definition(nameOfImage);
}

I am not that familiar with LESS so I think this works

Edit:

I am following this example from their homepage

.rounded-corners (@radius: 5px) {
border-radius: @radius;
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
}

#header {
.rounded-corners;
}
#footer {
.rounded-corners(10px);
}

also which part did not work? the background image? maybe try to take in the entire image path with the name as the variable

Dynamic CSS properties in LESS?

Below is the solution that lets you write your styles once using LESS, then compile them to be two different css stylesheets for both rtl, and ltr layouts.

basically we'll have three LESS files (they can be more!):

style-ltr.less  // this where we hold the rtl variables
style-rtl.less // rtl variables
main.less // here we'll write our styles

in style-ltr.less define the following variables:

@left: left;
@right: right;

@import "main.less";

while in style-rtl.less they will have the following values:

// reflect variables
@left: right;
@right: left;

@import "main.less";

now in main.less, we'll define the following mixins

.left(@distance) when (@left = left) {
left: @distance;
}
.left(@distance) when (@left = right) {
right: @distance;
}
.right(@distance) when (@right = right) {
right: @distance;
}
.right(@distance) when (@right = left) {
left: @distance;
}

// now we can style our elements using these mixins
div.something {
position: relative;
.left(10px);
float: @left;
}

now all we have to do is to include style-rtl.less in rtl pages include (or the compiled css version),
as well to include style-ltr.less in ltr pages, and div.something will be floated to the left on ltr pages, while it will be floated to the right on the rtl pages

Note that you can define padding, margin, border-radius ...etc. using the same way here.

UPDATE

I created two projects on github to help building a bi-directional applications

  • bi-app-less
  • bi-app-sass

Credits:

inspired by my dear friend Victor Zamfir

How to Change the Fill Value of a Background Image SVG Dynamically From CMS

So I ended up going a different route here and, rather than placing the SVG via a background image or content in CSS, I implemented it via HTML and set fill="currentColor." currenColor enables the SVG to inherit the color of the text in the button, as set in the CCMS. Code is below (in the form of a Twig Macro on Craft CMS). Code for setting the color of the button that the SVG inherits is in a separate template into which the macro is included.

{% macro button(url, text, options={}) %}

{% set svg %}
<svg class="btn__arrow" width="7px" height="20px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 6.799 10.477"><path data-name="Path 226" d="M6.8 5.238l-5.24 5.238L0 8.916l3.678-3.678L0 1.56 1.56 0z" fill="currentColor"/></svg>
{% endset %}

{% set options = {
target:'',
classes:'btn',
id:'',
type:'',
buttonStyle:'',
linkStyle: '',
svg: svg,
} | merge(options) %}

{% if options.type %}
<button {% if options.classes %}class="{{ options.classes }}"{% endif %} {% if options.id %}id="{{ options.id }}"{% endif %} {% if options.buttonStyle %}style="{{ options.buttonStyle }}"{% endif %} type="{{ options.type }}">{{ text | raw }} {% if options.svg | length %}{{ options.svg }}{% endif %}</button>
{% else %}
<a href="{{ url }}" {% if options.target %}target="{{ options.target }}"{% endif %} {% if options.classes %}class="{{ options.classes }}"{% endif %} {% if options.id %}id="{{ options.id }}"{% endif %} {% if options.buttonStyle %}style="{{ options.buttonStyle }}"{% endif %} {% if options.linkStyle %} style="{{ options.linkStyle }}"{% endif %}>{{ text | raw }} {% if options.svg | length %}{{ options.svg }}{% endif %}</a>
{% endif %}
{% endmacro %}


Related Topics



Leave a reply



Submit