tl:dr version: is there a way to #extend a css class and not have the original class appear in my compiled css without changing all my css classes to %placeholder classes?
Short answer based on the below answers: it appears there is no way to do this unless you go through and convert the css to silent/placeholder classes e.g. convert .one{} to %one{} and even then that will cause problems with media queries.
I have a css file (lets call it "style.css") which contains 200+ CSS classes to style various elements like forms and buttons etc. What I want is to include some of those classes in a project and other classes from that file in other random projects/websites. With each new project I also want to give the classes random semantic class names of my choosing.
My preprocessor of choice when working with CSS is SCSS and I really need an answer that uses the power of SCSS.
Here is a quick example of what I'm talking about - loading css into a SCSS file and then extending that css with my own class names:
//style.css
.one {
color: red;
padding-top: 1px;
}
//style2.scss
#import "style.css";
.two {
#extend .one;
}
The problem here is that my SCSS file will compile to CSS and look like this:
//style2.css
.one {
color: red;
padding-top: 1px;
}
.two {
color: red;
padding-top: 1px;
}
But what I want to do is only include the second class, which I gave a special name.
I've tried a few ways of doing this but here's one example that does not work but is along the lines of what I was thinking I should be able to do:
A.) First, I grab the style.css file and chuck copy/paste it into a style.scss file.
B.) Second I wrap all the whole thing in a placeholder/silent class, like so:
//style.scss
%placeholder {
.one {
color: red;
padding-top: 1px;
}
}
C.) Then I import that SCSS file and try and extend a class of my choosing that is within the placeholder, like this:
//style2.scss
#import "style";
.two {
#extend .one;
}
When I try and compile this I get a blank css file (and rightly so for trying to be too tricky). The other thing I know is that you can't extend nested selectors so "#extend %placeholder .one;" is also out of the question.
My question is this: does anyone know of a way to import and then extend a css class so that the compiled result does not include the imported css?
The only other solution I can think of is to just delete the imported css from the top of my file before I let it out into the wild. But this is honestly less than ideal solution.
Thank you in advance to any answers :)
You're using placeholders incorrectly, the placeholder should simply be one, no need to wrap it. Try this:
// style.scss
%one {
color: red;
padding-top: 1px;
}
// style2.scss
#import "style";
.two {
#extend %one;
}
Note that there is an issue with this approach. While the outputted CSS is leaner than using a mixin (#include), you will not be able to use %one inside of any #media queries. Ie. this will not work:
// style2.scss
#import "style";
#media screen and (max-width:1024px) {
.two {
// This won't produce CSS as it's inside the media query
#extend %one;
}
}
The only way I'm aware to get around this is to use a mixin instead of a placeholder which will result in more CSS (if you use one more than once).
// style.scss
#mixin one() {
color: red;
padding-top: 1px;
}
// style2.scss
#import "style";
#media screen and (max-width:1024px) {
.two {
#include one();
}
}
I've detailed the difference in output between mixins and placeholder selectors on my blog if you're not aware.
Related
This question already has answers here:
How to extend css class with another style?
(7 answers)
Closed 4 years ago.
In Bootstrap 4 I can use text-truncate as a class in an element. Eg:
<span class="text-truncate">Any very long text</span>
What I need now is to use this class text-truncate in a scss file for many objects instead of writing it directly in .html files.
How to?
Can I use something like:
#import "text-truncate" from "bootstrap.scss";
.myBeautifulDiv {
use text-truncate;
}
This would be great! Is it possible?
U can create placeholder classes in scss,
Placeholder classe names start with %.They, themselves, will not be included in the the output css files.
But they can be imported into other classes. Check example below.
Just remember to load your bootstrap css first.
/*In bootstrap file*/
.text-truncate{
text-overflow:ellipsis;
...
...
}
/*In your scss file*/
%truncatedtext { /*This is placeholder class*/
#extend .text-truncate; /*This will include/pull the actual bootstrap code*/
}
.class-a {
#extend %truncatedtext;
color: #000000;
}
.class-b {
#extend %truncatedtext;
color: red;
}
Its output will be
.text-truncate, .class-a, .class-b {
/*trucate css code*/
}
.class-a {
color: #000000;
}
.class-b {
color: red;
}
Totally possible. Go here (https://getbootstrap.com/docs/4.1/getting-started/download/), click "Download Source", and what you're looking for is probably in the _scss folder.
I'm using the SASS port of Bootstrap, and I'm wondering if there's any difference between using the pre-defined mixins and using SASS's #extend.
For instance, if I have:
<div class="wrapper">
Some content here....
</div>
Is there any difference between doing
.wrapper {
#include make-row();
}
and
.wrapper {
#extend .row;
}
?
If there's no difference, are there other mixins that aren't equivalent to a single #extend statement? If there aren't such mixins, why do the mixins even exist?
The big difference between #extend and a mixin is the way the css is compiled. It doesn't look like much in simple examples, but the differences and implications are significant and can be a real headache in the wild if used carelessly. #extend is a little bit like fools gold, looks great at first, but ...
Let's look at a simple example:
#extend
.row {
width: 50px;
}
.new-row {
#extend .row;
}
.another-row {
#extend .row;
}
compiles into:
.row,
.new-row,
.another-row {
width: 50px;
}
mixin
#mixin row() {
width: 50px;
}
.new-row {
#include row();
}
.another-row {
#include row();
}
compiles into:
.new-row {
width: 50px;
}
.another-row {
width: 50px;
}
A mixin includes the properties everywhere it is hit - copying them each time - whereas an #extend groups the selectors and defines the properties once. This isn't immediately obvious, because the difference is in the compiled css but it has some important implications:
Load order
With #extend the selectors will be grouped at the first point in the sass where they are encountered which can lead to some weird over-riding. If you define a selector and use #extend to bring in a property to and try to override a property defined earlier in your sass, but after the point at which the extended properties are grouped in the css then the override will not work. This can be quite perplexing.
Consider this logically ordered set of css definitions and the likely HTML: <div class='row highlight-row'></div>:
.red-text {
color: red;
}
.row {
color: green;
}
.highlight-row {
#extend .red-text;
}
compiles into:
.red-text,
.highlight-row {
color: red;
}
.row {
color: green;
}
So even though the sass ordering makes it look like the row colour would be red, the compiled css will make it green
Poor groupings
#extend can result in poorly grouped selectors in the resulting css. You can end up with thirty or forty unrelated things all sharing the same property for example. Using #extend for fonts is a good example of this.
Nesting
If you are using deeply nested sass (which is not good, btw) and you use #extend you will duplicate the fully nested selector for every #extend you use, resulting in bloated css. I've seen this a lot:
.selector-1 .selector-2 .selector-3 .selector-4,
.selector-1 .selector-2 .selector-3 .selector-4 a,
.selector-1 .selector-2 .selector-3 .selector-4 li,
.selector-1 .selector-2 .selector-3 .selector-4 td {
font-family: arial;
}
If you're new to SASS it pays to look at the compiled css.
Media queries
#extend do not work inside media queries, because media queries are not selectors.
Conclusion
My rule of thumb is to use an #extend over a mixin if you have no parameters and if you can reasonably define the #extend and share it amongst a few tightly related selectors that exist nearby in the sass, for example, in the same file that defines a sass module. Buttons are a good example of well used #extend:
%button {
padding: 10px;
}
.call-to-action {
#extend %button;
background-color: $green;
}
.submit {
#extend %button;
background-color: $grey;
}
The best article to help make the choice is here
PS, the % sign is a use of placeholder extends
Say I am using SASS and I want to borrow heavily from some existing stylesheet, be it another SASS stylesheet or a CSS one. I can #import that other sheet, then use #extend to use some of its rules. Is there an option to then exclude all the other stuff I didn't use from the resulting CSS?
#import takes the whole stylesheet/partial and puts it in your stylesheet, there's no way to exclude any of the rules aside from overwriting them all to defaults. If you have an originating SASS file you could abstract them all into partials and then #import what you need into your new file.
There's no way to import another sass file so that #extends can be used without rendering the content. Create and import a partial full of %placeholders to use #extend without renders content would be a good choice if it wasn't be rendered like this:
_import.scss
%button {
color: #fff;
width: 72px;
height: 24px;
}
main.scss
#import "import";
.button-blue {
#extend %button;
background-color: blue;
}
main.css
.button-blue {
color: #
width: 72px;
height: 24px; }
.button-blue {
border: 1px solid #fff; }
So I think that the best way to achieve your goal is import a partial with some mixins in your style, I 've been using sass for half a year and so far I haven't had a need to import #extends yet so please, tell me what you want to do exactly with the #extend and I will try to help you to get it with a #mixin
I've tried to find the answer, and can't seem to do so, which is leading me to believe that it isn't possible. With my minimal knowledge of how CSS works, I also don't think it would be possible, but I just want to ask before I start working around a problem that may or may not exist.
Basically what I'm trying to do is use a previously defined attribute in a new class in my CSS stylesheet. For instance, say I had a couple of classes that just held background or font colors, like this:
.black { background-color: #000000; color: #000000; }
.white { background-color: #FFFFFF; color: #FFFFFF; }
Now if I was defining a new class (or using any selector for that matter), would it be possible to use the value of an attribute from an already existing class? Here is what my idea would look like:
.newClass {
width: 100%;
height: 100%;
background-color: .black; /* this would just get the background-color attribute from the .black class definition */
}
background-color: .black; is basically just a placeholder for "get the background-color attribute from the .black class definition". Is that possible using purely CSS? I'm aware of a ton of alternatives with PHP/JS, but I'd like to know if CSS can tackle this by itself. Thanks guys.
SASS is a thing to go. Your code will be like
#mixin black-theme {
.black { background-color: #000000; color: #000000; }
}
.newClass {
width: 100%;
height: 100%;
#include black-theme;
}
SASS
PHP compiler for SASS PHPSASS
There are javascript based solutions too like LESS but I generally don't recommend them as if Javascript load slow then presentation becomes jerky.
No, this is not currently possible in CSS. CSS does not have variables or the ability to reference values from previous rules. You would have to look for a CSS preprocessing language that gets processed into plain CSS before going onto the web site.
If you're willing to go the preprocessed way, you can look at SASS or LESS.
Yea possible using SASS or LESS css
#bgcolor : black;
.newClass {
width: 100%;
height: 100%;
background-color:#bgcolor;
}
I have researched SASS and Blueprint seperately, and think I understand how they work, and I have set up my project directory using the compass CLI tool, but I am at a loss as to the correct way to organize my project.
After initializing my project with
$ compass create my_project --using blueprint/semantic
...I was told to link the generated CSS files in my HTML with these lines
<link href="/stylesheets/screen.css" media="screen, projection" rel="stylesheet" type="text/css" />
<link href="/stylesheets/print.css" media="print" rel="stylesheet" type="text/css" />
...but where should I put my own application-specific .scssfiles and how should I include the appropriate blueprint files?
It seems to me that I should not be including the generated print.css and screen.css directly into my HTML but instead doing something like:
#import "screen";
body {
#include container;
}
...and then using only the file generated from the above in my HTML. Otherwise why would we have a line like this in screen.scss?:
// Import all the default blueprint modules so that we can access their mixins.
#import "blueprint";
I can't use mixins in my HTML.
I'm finding the docs to be very vague and contradictory, and any sort of short example illustrating the combination of:
HTML
SCSS files generated from compass command above
SCSS files containing site-specific styling
would be very helpful for me and probably others.
The "screen.scss" and "print.scss" files are nothing magical. These are just example filenames given to the output which you can link from your HTML, but you don't have to: just delete them and create your own files if you prefer, or add your own styles to them. The intent with these 2 files is to keep the style concerns organized separately: you could add a "mobile.scss" and then link all these in your HTML, or import them together into one master file under #media blocks.
I can't use mixins in my HTML.
Mixins don't apply to your HTML. They are a helpful technique used for writing your SCSS source code: the compiled CSS output or the HTML doesn't know anything about them. You should be using mixins to take advantage of Sass.
I have researched SASS and Blueprint seperately
It's important to understand what the Blueprint classes do first, but when you use Compass there are different approaches for how you apply frameworks like Blueprint:
1. Use Blueprint's original non-semantic class names throughout your HTML
This is not considered best-practice, but it's a way to get started especially when wireframing/scaffolding:
screen.scss
#import "blueprint";
// This outputs Blueprint's classes into your stylesheet:
#include blueprint;
#sidebar { background: $blue; }
#main { background: $yellow; }
screen.css (compiled)
.column { float: ... }
.span-6 { width: ... }
.span-12 {width: ... }
/* ...etc., all of Blueprint's classes ... */
#sidebar { background: #ccf; }
#main { background: #ffc; }
index.html
<div id="sidebar" class="column span-6">sidebar content</div>
<div id="main" class="column span-12">main content</div>
The result is the same as using Blueprint without Sass/Compass. Your HTML would contain the presentational classes, which are really not too different from just using style="width:120px" on your elements: it's just done using classes instead.
2. Use Blueprint as mixins into your own semantic class names:
screen.scss
#import "blueprint";
// Do not output Blueprint's classes into your stylesheet.
// Instead, write your own classes and mixin the functionality:
#sidebar {
#extend .column;
#include span(6);
background: $blue; }
#main {
#extend .column;
#include span(12);
background: $yellow; }
screen.css (compiled)
.column, #sidebar, #main { float: left; ... }
#sidebar { width: 240px; background: #ccf; }
#main { width: 480px; background: #ffc; }
index.html
<div id="sidebar">sidebar content</div>
<div id="main">main content</div>
As you can see, the second method moves Blueprint's presentation logic out of the HTML and into the stylesheet.
The judicious use of #extend (instead of #include) is an optimization that lets you group common styles together, e.g. all the elements that are "columns" are defined once as a list of selectors; only their different widths are included directly into each element.