LESS CSS prepend mixin reference with child selector - css

Is there any way I can use the immediate child selector without having to do it inside the mixin to get the desired result? The real mixin is actually large and I want to be able to reuse it also without having to pollute it with child selectors.
Desired Result
.wrapper > .col-xs-6 {
width: 50%;
}
Code I have
.wrapper {
> .mixintest(); //not allowed
}
.mixintest(){
.col-xs-6{
width: 50%;
}
}

move immediate child selector to mixin
.wrapper {
.mixintest();
}
.mixintest() {
> .col-xs-6 {
width: 50%;
}
}
That is the only way that will work according to
https://lesscss.org/features/#mixins-feature
more specifically this example in "Namespace" subsection
#outer > .inner(); // deprecated
#outer .inner(); // deprecated
#outer.inner(); // preferred

Related

scss continue name with interpolation and `#at-root`

I am trying to fully understand the ampersand (&) and interpolation operators in sass, while also following bem. For example, I have a table block declared like so:
.table {
width: 60%;
&__title {
// omit code
}
&__data {
display: grid;
width: 100%;
& > #{#at-root}__key + #{#at-root}__value > * { // <- ISSUE HERE
// give all direct, non text child nodes margin below
margin-bottom: 0.5em;
}
}
}
and used like:
<div class='table'>
<div class='table__title'>...</div>
<div class='table__data'>
<div class='table__key'>...</div>
<div class='table__value'>...</div>
</div>
</div>
See line 9 of the sass; here the expected compiled result would be
.table__data > .table__key + .table__value > * {
margin-bottom: 0.5em;
}
but of course #at-root is not a variable so an error is thrown
SassError: Invalid CSS after "#": expected expression (e.g. 1px, bold), was "#at-root}__key + #{"
Does anything like my attempt exist, can/should I somehow combine the #at-root element with classes I'm using?
Articles I've already tried:
Append the parent selector to the end with Sass
EDIT made the question clearer
What I do when I actually deem this necessary is to just create your reference from the root. It's kind of like the old days when you often had to declare that = this scenarios (well not really but you get the idea lol).
However, generally I avoid this kind of deep nesting unless it's genuinely required to avoid too many levels of specificity (habit from the old days when such noticeably things effected performance.
See example below, and a codepen to tinker
.table {
$root: &; // <-- create reference to root that allows interpolation.
width: 60%;
&__title {
// omit code
}
&__data {
display: grid;
width: 100%;
& > #{$root}__key + #{$root}__value > * { // <- ISSUE HERE
// give all direct, non text child nodes margin below
margin-bottom: 0.5em;
}
}
}
...and the compiled output...
.table {
width: 60%;
}
.table__data {
display: grid;
width: 100%;
}
.table__data > .table__key + .table__value > * {
margin-bottom: 0.5em;
}

"Resting" & in Sass

I'm importing sass classes from another project and want to provide a wrapper to keep these styles localised.
My wrapper looks like this
.my-wrapper {
#include "framework-main"
}
I first looked fine but then I noticed that some tiles are missing. The problem is that the framework sass files use heavily reference to parent: &. This works fine for them but when I apply the wrapper it's get injected everywhere.
How can I make the wrapper a prefix only?
To illustrate:
SASS:
.wrapper {
// reset here somehow, I have no control over the nested code.
.parent {
&--child1 &--child2 {
width: 10%;
}
}
}
What I want:
.wrapper .parent--child1 .parent--child2 {
width: 10%;
}
What I get:
.wrapper .parent--child1 .wrapper .parent--child2 {
width: 10%;
}
Is this even possible?
Yes, it is possible, there is just small mistake in your code - you don't need . in front of &--child so it will not break selector construction:
.wrapper {
// reset here somehow
.parent {
&--child {
&--grand-child{
width: 10%;
}
}
}
}
gives
.wrapper .parent--child--grand-child {
width: 10%;
}

LESS selectors: how to apply styling only for one of the elements from inside mixin?

I have a code that I can't change:
item.left,
item.centre,
item.right{
.MIXIN();
}
.MIXIN(){
width: 100px;
}
I need to apply width only to .right element. I can only change contents of MIXIN(). I was thinking of using &but it will result either in .right item.right or item.right .right which is not what I want. Is there a way to apply styling only for .right element using contents of MIXIN()?
You can use the negation CSS pseudo-class :not().
item.left,
item.centre,
item.right{
width: 20px;
&:not(.left):not(.centre) {
width: 100px;
}
}
Fiddle: https://jsfiddle.net/e0nd7pk4
You can not do it. The only way is to override the first declaration.
item.left,
item.centre {
width: inherit;
}
How about & but without the space:
.MIXIN() {
width: 100px;
&.right { color: red; }
}
It compiles down to item.right.right which is a bit weird but won't match left and center.
Fiddle: http://jsfiddle.net/c0634wg2/

How do I write any positioning into a LESS variable?

So I was writing up some code when I decided I wanted to make a variable for margin and padding, along with some other positioning too. But when I try I get errors.
This is what my code looks like:
//Positioning
#margin_t: margin-top:0;
#margin_r: margin-right:0;
#margin_l: margin-left:0;
#margin_b: margin-bottom:0;
#padding_t: padding-top:0;
#padding_r: padding-right:0;
#padding_l: padding-left:0;
#padding:_b: padding-bottom:0;
#center: text-align: center;
#left: text-align: left;
#right: text-align: right;
#relative: position: relative;
#justify: position: justify;
Can anyone give me their two-cents? Thank you!
As of LESS 1.7
You can include property values in variables by rulesets, like so (note bracketing and following semicolon; p.s. position: justify is not valid, I've changed it to absolute):
//Positioning
#margin_t: {margin-top:0;};
#margin_r: {margin-right:0;};
#margin_l: {margin-left:0;};
#margin_b: {margin-bottom:0;};
#padding_t: {padding-top:0;};
#padding_r: {padding-right:0;};
#padding_l: {padding-left:0;};
#padding:_b: {padding-bottom:0;};
#center: {text-align: center;};
#left: {text-align: left;};
#right: {text-align: right;};
#relative: {position: relative;};
#absolute: {position: absolute;};
A variable assigned ruleset is use much like a mixin (note the parentheses on the call), so:
.yourClass {
#relative();
}
Produces:
.yourClass {
position: relative;
}
The differences of a variable ruleset to a mixin are that you cannot pass parameters to a ruleset (directly anyway), but a ruleset can itself be passed as a parameter to a mixin. Also, variable rulesets will overwrite a previous definition (no matter properties defined), whereas mixins will merge property values. Rulesets work well for fixed values, like some of your items. They can be parametrized indirectly, something like so:
#margin_t: {margin-top: #tm;};
.yourClass {
#tm: 0;
#margin_t();
}
Varible rulesets actually work best for when one wants to pass to a mixin a group of properties or a single, unknown dynamic property. As an example of the latter, suppose you know you will want to set a single margin for an element, but depending on some context, you don't know which you want to set, so you want a single way to handle it. Then something like this can be done:
#margin_t: {margin-top: #value;};
#margin_r: {margin-right: #value};
#margin_l: {margin-left: #value;};
#margin_b: {margin-bottom: #value;};
.set-a-margin(#prop; #value: 0;) {
#prop();
}
.yourClass {
.set-a-margin(#margin_r; 10px);
}
.anotherClass {
.set-a-margin(#margin_b; 5px);
}
Produces:
.yourClass {
margin-right: 10px;
}
.anotherClass {
margin-bottom: 5px;
}
Basically, variable assigned rulesets just offer another way LESS can be used to code the way you may want to code. They can offer some functionality like mixins, with certain limitations and advantages different from those as related to variables.
Firstly, define your mixins like this:
.margin_t {
margin-top: 0;
}
.margin_b (#value: 0) {
margin-bottom: #value;
}
and then just use it!
body {
.margin_t();
.margin_b(15px);
}
You don't set the whole style. you would do #margin_t: 0;
Then use it
.myClass {
margin-top: #margin_t;
}

CSS inheritance, or something like that

This is probably silly question, but here it goes.
I have 3 ID in my css file, and they all have some same code. For example:
#ID1 {
// some code
width: 300px;
height: 300px;
}
#ID2 {
// some code
width: 300px;
height: 300px;
}
#ID3 {
// some code
width: 300px;
height: 300px;
}
MY question is: is is possible to make some class or ID in CSS and call it inside another CSS class or ID. For example:
#setting {
width: 300px;
height: 300px;
}
#ID1 {
.setting
// some code
}
#ID2 {
.setting
// some code
}
#ID3 {
.setting
// some code
}
Thanks.
What you are looking for is called LESS. Read about it here
You can override css by applying reference to its parent class, check below example :
#setting {
width: 300px;
height: 300px;
}
#ID1 .setting {
// some code
}
#ID2 .setting {
// some code
}
#ID3 .setting {
// some code
}
above code will apply all the "setting" class tag inside ID1, ID2, ID3 respectively.
If your "setting" child is immediate class then you can you below as example :
#setting {
width: 300px;
height: 300px;
}
#ID1 > .setting {
// some code
}
#ID2 > .setting {
// some code
}
#ID3 > .setting {
// some code
}
Above code will only apply to its immediate child named with class "setting".
You can use multiple CSS classes on a single element.
You can create the "generic" classes and apply them to the elements.
For example:
<div class="class1 class2">some content</div>
Remember that if there is a common property in class1 and class2, the value of that property in class2 will overwrite the one in class1 on that element and ultimately the element will have the value defined in class2.
Really old browsers don't support this but most probably you shouldn't worry about them.
No, it is not possible in CSS, and it has nothing to do with inheritance. In CSS rules, you put all the selectors before the “{” and only declarations (property : value) between “{” and “}”.
But you can use both an id attribute and a class attribute on an element, as in
<div id="ID1" class="setting">...</div>
and then if you have e.g.
.setting {
width: 300px;
height: 300px;
}
(note: . not #), these declarations are applied to all elements with class=setting, along with any other declarations that may apply due to other CSS rules.

Resources