I'm having some trouble understanding the placeholder behavior for selectors when compiled into css. So I've created a placeholder inside a class selector (.test) and I'm trying to extend it into another class (.test1) inside a third class (.test2). it compiled into css without any error although I'm curious how the selectors formed when compiled. here are the output and code snippets.
This is not actual use case but I'm just wondering how the selectors formed in the output?
.test {
%placeholder {
font-size: 14px;
}
}
.test2 {
.test1 {
#extend %placeholder;
}
}
Output
.test .test2 .test1, .test2 .test .test1 {
font-size: 14px;
}
Related
One can do #extend .foo but apparently not #extend .foo:focus.
I'm dealing with a 3rd party component which adds it's own focused class when it considers it is focused. Using #extend to apply Bootstrap styles works fine, but because the 3rd party component does not get a :focus the .form-control:focus is never matched.
My SCSS in principal would be:
.thirdparty {
#extend .form-control;
}
.thirdparty.thirdparty-focused {
#extend .form-control:focus;
}
#extend .form-control:focus; does not compile however.
Currently I can't figure out how to do this without copying the .form-control:focus CSS into .thirdparty.thirdparty-focused, which is obviously rather unideal.
Is some sort of #extend .form-control:focus; equivalent possible, and if not, any suggestions better than copying N lines of CSS to match the rest of Bootstrap?
#extend .form-control:focus will act as a selector, specifically looking for a rule named .form-control:focus. Here is an illustration.
The best solution to your problem would be to outsource the :focus pseudo-selector of the original Bootstrap class, using the %-selector, and then re-extend it into it - so that you could call it seperately.
%focus {
color: #2196f3;
}
.base {
color: #000;
&:focus {
#extend %focus;
}
}
div {
#extend .base;
&.focus {
#extend %focus;
}
}
// Other Bootstrap components can still call `#extend .base;`
This will compile to:
.base:focus, div:focus, div.focus {
color: #2196f3;
}
.base, div {
color: #000;
}
When I tried this, the error message basically told me what to do:
SassError: compound selectors may no longer be extended.
Consider `#extend .form-control, :focus` instead.
Using this should work (don't forget necessary imports to bootstrap):
.thirdparty.thirdparty-focused {
#extend .form-control, :focus;
}
In a scss file, I saw the below code snippet:
#mixin myMixin() {
:global(.rtl) & {
#content;
}
}
I understand the keywords #mixinas well as #content and tried to understand :global() from this link:
What does :global (colon global) do?.
But I am not sure what "&" does here or what this whole mixin does.
The ampersand (&) is a combinator used in nesting and in this case it is being used to qualify a selector.
For a general example:
// This Sass...
.foo {
.bar & {
color: red;
}
}
// ...would compile to this CSS
.bar .foo { color:red; }
In your example, the mixin declaration replaces .foo, and would look like:
// If you called your mixin at .bar
.bar {
#include myMixin {
color: red;
}
}
// It should compile to something like this
:global(.rtl) .bar { color: red; }
More details about ampersands and qualifying selectors in this CSS Tricks article.
Here are two mixins
#mixin parent {
.parent & {
#content;
}
}
#mixin child($child) {
.#{$child} & {
#content;
}
}
Both mixin works fine independently.
Things which am looking for:
child can be independent
Also child mixin can be included in parent but opposite
should not be allowed.
In case someone tries to include parent into child there should
be some error message.
In css output .parent should come before .child(see example below for this point)
Point 4 example:
.test {
//some css properties
#include parent {
#include child(childboy) {
color: red;
}
}
}
as you can see this will give following output
.childboy .parent .test {
color: red;
}
As you can see .parent class is coming after .childboy.
How can we make it .parent class to come before .childboy
.parent .childboy .test {
color: red;
}
Is it possible to do with scss??
Please answer only in scss.
Thank you.
I don't think you can do it that way.
Check out this CSS-tricks post:
The & doesn't allow you to selectively traverse up your nested
selector tree to a certain place and only use a small portion of the
compiled parent selector that you want to use.
If I understand correctly, the reason why you're trying to do this with SCSS is because you want to group the .parent .childboy .test selector within .test root selector.
Here's a different way to do this with SASS:
.test {
#at-root .parent .childboy & {
color: red;
}
}
Codepen demo
Note: the trailing & appends the selectors from root downwards - here, just the .test class
From the SASS docs:
The #at-root directive causes one or more rules to be emitted at the
root of the document, rather than being nested beneath their parent
selectors.
I don't understand why the code below generates .test a.test {color: black;}
instead expected a.test {color: black;}?
I thought it's an opposite method to &.a which generates just test.a (in this case).
.test {
width: 10px;
a#{&} {
color: black;
}
}
I just found a solution to style a.test with class a nested in .test.
There is a special sass directive #at-root which allows to emit a style block at root of the list.
// Sass
.test {
#at-root a#{&} {color: blue;}
}
// Generated CSS
a.test {color: blue;}
Demo
Is there a way to get the below to work?
.class1 {
line-height:20px;
}
.class2 {
height: class1.line-height;
}
I know that css variables would be the way to go but since it is in experimental phase, it would not be a suitable for our project. Is there any other way?
You can't really use dependencies like that in CSS without a preprocessor such as SASS or LESS. But you can apply more than one class to the HTML.....
<div class="class1 class2"></div>
In this case, class1 would contain the line-height, then class2 would contain any other properties you want to apply to that particular div.
Any similar properties between class1 and class2 would allow class2 to take precedence, since it's loaded after class 1, assuming the CSS hierarchy is logical.
For example:
.class1 { line-height: 1.3; background-color: red;}
.class2 { background-color: blue; }
The div would have a line-height of 1.3x and a background color of blue.
yeah.. you can't use dependencies like that in CSS.
you have to use SASS or LESS..
you can do like this in SASS
.class1 {
line-height:20px;
}
.class2 {
#extend.class1
}
Five years later...
I know that css variables would be the way to go but since it is in experimental phase, it would not be a suitable for our project.
As it's 2021 (and no-one is using Internet Explorer 11 anymore, phew, and all the major browsers fully support CSS Variables CSS Custom Properties) so you can now use var().
If you simply want to only define 20px once to avoid repeating yourself in CSS, then set a custom-property on a common ancestor of both .class1 and .class2 elements: most people use html (or html:root or just :root) for this:
:root {
--my-height: 20px;
}
.class1 {
line-height: var(--my-height);
}
.class2 {
height: var(--my-height);
}
Now, if you want .class2 elements to "inherit" their height: from any ancestor class1 elements instead of <html>, then this should work:
:root {
--my-height: 50px; /* Default value for .class2 elements which are not descendants of .class1` */
}
.class1 {
--my-height: 20px; /* Redefining the value */
line-height: var(--my-height);
}
.class2 {
height: var(--my-height);
}
...or if you want only .class2 descendants of .class1 to use the value:
:root {
}
.class1 {
--my-height: 20px;
line-height: var(--my-height);
}
.class1 .class2 {
height: var(--my-height);
}
But you probably shouldn't be setting line-height anyway - doing-so is a sign that you're misusing display: inline; or vertical-align:;.