css mixins using an external framework - css

How can you use css mixins based on an existing library? Example: Consider you want to create a new css class based on the bootstrap btn btn-success classes. It might look like:
.disabled-button {
#mixin .btn;
#mixin .btn-success;
#mixin .disabled;
color:red;
}
Less/Sass are capable of doing such kind of things when you define the classes btn or btn-success yourself, but how do you deal with it when it comes from bootstrap (or another css framework) ?

If you can add LESS compilation into your workflow, you can achieve this easily with its #import (reference) and :extend(x all). Without needing to learn anything more about LESS, you'd do
#import (reference) "bootstrap.less"; // this file is included with bootstrap. `(reference)` means it will only pull in the styles you ask it for, so you could continue using this even if you switch to another framework and don't want to include all of bootstrap
.disabled-button:extend(.button all, .button-success all, .disabled all) {} // pulls in the `.button` styles, `.button-success` styles, and `.disabled` styles
.disabled-button {color:red} // adds on your styles
Explanation of LESS's :extend(all) and relevant documentation links are in this answer
Since CSS is valid LESS, you wouldn't have to make any other changes to your stylesheet. Okay, so how do you add LESS compilation to your workflow? The simplest solution is described in LESS's "Command Line Useage" documentation, which boils down to installing less (once)
$ npm install less -g
and then running lessc, the less compiler
$ lessc my-styles.less my-compiled-styles.css

Related

Is there a way to compose css classes using other css classes?

I have been looking at tailwind CSS, when I am using it, it feels like writing style inside HTML. Which makes this an awkward library to use for me. But while I was looking at it I got an idea.
Instead of using tailwind like this
<div class="p-4 flex text-lg">Something</div>
Is it possible for me to do this using some CSS preprocessor:
// in html
<div class="some">Something</div>
// in css (with a preprocessor)
.some {
include: .p-4;
include: .flex;
include: .text-lg;
}
This way I don't have to write style in HTML but still get the benefits of tailwind's utility classes.
I know Scss has mixins, but as far as I know tailwind only provides classes and not mixins, and I have no experience with any other CSS preprocessor. So is there any preprocessor that supports this feature?
With SCSS, #extend could do the job. However, it will only work if you have access to the classes you want to extend. As for Tailwind CSS, I think #apply is the built-in way to do what you want.

Is it possible to #extend Foundation SCSS classes?

Using the tools provided by Zurb's Foundation as they were intended means you have to compromise your HTML-markup. You'll be adding classes the HTML doesn't need just to pull in that Foundation functionality.
Using the SASS source code I'm trying to avoid aforementioned problem by using #extend.
Some example HTML markup I want to avoid
<nav id="main_navigation" class="top-bar">
By doing this
#main_navigation {
#extend .top-bar;
}
I realise this would still compile to redundant CSS as well as probably break the JS functionality for the topbar, but let's save that for another question.
The issue is that it doesn't work! Styles that apply to children of .top-bar as well as any pseudo-classes don't get extended to apply to #main_navigation. I tried to recreate the problem in a CodePen, but the compiled code over there is flawless.
So is this a structural problem in Foundation? Or am I messing something up?
I use a Grunt task with grunt-sass to compile the Foundation SASS with my own code after it.
After some more extensive debugging using CodePen I figured the issue had to be in the compiler.
Switching from grunt-sass to the more stable (but slower) grunt-contrib-sass made all unexpected behavior disappear.
Yes, you can #extend Foundation SCSS

Using #extend-Only to abstract Bootstrap selectors

I have several styles that use Sass' #extend or #include to inherit properties from selectors imported from Bootstrap scss files.
I would like to convert all of the Bootstrap selectors to #extend-Only placeholders, so I do not have to include any original Bootstrap selectors in my final .css output. The goal is to write my own css classes, extend from Bootstrap only where desired.
For example, I wish to have a navbar called .super-freaky-nav:
.super-freaky-nav{
#extend .navbar;
#extend .navbar-default;
#extend .navbar-top-fixed;
}
Ideally, my final .css output will not have a single reference to .navbar, .navbar-default, or .navbar-top-fixed.
Is there a way to do this without going into the _navbar.scss file and converting all of the selectors to #extend-Only classes (%navbar, %navbar-default, %navbar-top-fixed, etc)?
Thanks!
No. Sass does not have the ability to do what you're asking for. There's still a legitimate need to be able to extend normal classes and Sass has no way of differentiating between classes that should or shouldn't be extended.
One potential implementation I'm exploring uses custom importers in ruby-sass or the experimental importers feature in node-sass (2.0+) to apply a sed (find and replace) transform to the Bootstrap Sass files, replacing leading class definitions with % syntax. I haven't gotten much past experimentation, though, and I don't know what I might break without a comprehensive visual test suite. Happy to have some help with it.

Is it possible in SASS to inherit from a class in another file?

The question pretty much says it all.
For instance, if I were using, say, Twitter Bootstrap, could I define classes in my own SASS stylesheet that inherit from Bootstrap's CSS classes? Or does inheritance in SASS only work within the scope of a single file?
YES! its possible.
If you want all <button> elements to inherit the .btn class from Twitter Bootstrap's Default buttons
In your styles.scss file you would have to first import _bootstrap.scss:
#import "_bootstrap.scss";
Then below the import:
button { #extend .btn; }
**I might be mistaken, but if I get what you're trying to do, can't you just use the #extend .classname; command inside the element that you'd want to extend? Naturally, you should only modify your own code to preserve updatability.
To my knowledge, you have to use #import of the file containing the classes you want to use into your SASS file in order to utilize them in that file. However, I am not a SASS/SCSS expert, so someone may know of another way to remotely use them that I am not aware of.
Just as the accepted answer has shown this is possible with #import, however #import has been deprecated by sass
The Sass team discourages the continued use of the #import rule. Sass will gradually phase it out over the next few years, and eventually remove it from the language entirely. Prefer the #use rule instead.
The #use rule is better suited for use now, since it does not pollute the scope of the importing (user) module. unfortunately at the time of writing the use rule is only implemented in Dart sass.

Customizing Bootstrap CSS template

I am just getting started with Bootstrap from Twitter and am wondering what the ‘best practices’ is for customization. I want to develop a system that will take advantage of all the power of a css template (Bootstrap or other), be completely (and easily) modifiable, be sustainable (ie – when the next version of Bootstrap is released from Twitter I don’t have to start over.
For example, I want to add background images to the top navigation. It looks like there are 3 ways to go about this:
Modify the .topbar classes in bootstrap.css . I don’t particularly like this because I will have lots of .topbar items and I don’t necessarily want to modify them all the same way.
Create new classes with my background images and apply both styles (the new and the bootstrap to my element). This may create style conflicts, which could be avoided by stripping the .topbar class into separate classes and then only using the pieces that are not stepped on by my custom class. Again this requires more work than I think should be necessary and while it is flexible, it won’t allow me to easily update bootstrap.css when Twitter releases the next installment.
Use variables in .LESS to achieve the customization. Offhand this seems like a good approach but having not used .LESS I have concerns about compiling css on the client and about code sustainability.
Though I am using Bootstrap, this question can be generalized to any css template.
The best thing to do is.
1. fork twitter-bootstrap from github and clone locally.
they are changing really quickly the library/framework (they diverge internally. Some prefer library, i'd say that it's a framework, because change your layout from the time you load it on your page). Well... forking/cloning will let you fetch the new upcoming versions easily.
2. Do not modify the bootstrap.css file
It's gonna complicate your life when you need to upgrade bootstrap (and you will need to do it).
3. Create your own css file and overwrite whenever you want original bootstrap stuff
if they set a topbar with, let's say, color: black; but you wan it white, create a new very specific selector for this topbar and use this rule on the specific topbar. For a table for example, it would be <table class="zebra-striped mycustomclass">. If you declare your css file after bootstrap.css, this will overwrite whatever you want to.
Bootstrap 5 (update 2021)
As explained in the Bootstrap docs, modifying the existing "theme" colors is done using SASS. As with prior versions, you can also override the Bootstrap CSS by adding CSS rules that follow after the bootstrap.css and use the correct CSS specificity.
Bootstrap 5 - change theme colors
Bootstrap 4
I'm revisiting this Bootstrap customization question for 4.x, which now utilizes SASS instead of LESS. In general, there are 2 ways to customize Bootstrap...
1. Simple CSS Overrides
One way to customize is simply using CSS to override Bootstrap CSS. For maintainability, CSS customizations are put in a separate custom.css file, so that the bootstrap.css remains unmodified. The reference to the custom.css follows after the bootstrap.css for the overrides to work...
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/custom.css">
Just add whatever changes are needed in the custom CSS. For example...
/* remove rounding from cards, buttons and inputs */
.card, .btn, .form-control {
border-radius: 0;
}
Before (bootstrap.css)
After (with custom.css)
When making customizations, you should understand CSS Specificity. Overrides in the custom.css need to use selectors that are the same specificity as (or more specific) the bootstrap.css.
Note there is no need to use !important in the custom CSS, unless
you're overriding one of the Bootstrap Utility
classes. CSS
specificity
always works for one CSS class to override another.
2. Customize using SASS
If you're familiar with SASS (and you should be to use this method), you can customize Bootstrap with your own custom.scss. There is a section in the Bootstrap docs that explains this, however the docs don't explain how to utilize existing variables in your custom.scss. For example, let's change the body background-color to #eeeeee, and change/override the blue primary contextual color to Bootstrap's $purple variable...
/* custom.scss */
/* import the necessary Bootstrap files */
#import "bootstrap/functions";
#import "bootstrap/variables";
/* -------begin customization-------- */
/* simply assign the value */
$body-bg: #eeeeee;
/* use a variable to override primary */
$theme-colors: (
primary: $purple
);
/* -------end customization-------- */
/* finally, import Bootstrap to set the changes! */
#import "bootstrap";
This also works to create new custom classes. For example, here I add purple to the theme colors which creates all the CSS for btn-purple, text-purple, bg-purple, alert-purple, etc...
/* add a new purple custom color */
$theme-colors: (
purple: $purple
);
https://codeply.com/go/7XonykXFvP
With SASS you must #import bootstrap after the customizations to make them work! Once the SASS is compiled to CSS (this must be done using a SASS compiler node-sass, gulp-sass, npm webpack, etc..), the resulting CSS is the customized Bootstrap. If you're not familiar with SASS, you can customize Bootstrap using a tool like this theme builder I created.
Custom Bootstrap Demo (SASS)
Note: Unlike 3.x, Bootstrap 4.x doesn't offer an official customizer tool. You can however, download the grid only CSS or use another 4.x custom build tool to re-build the Bootstrap 4 CSS as desired.
Related:
How to extend/modify (customize) Bootstrap 4 with SASS
How to change the bootstrap primary color?
How to create new set of color styles in Bootstrap 4 with sass
How to Customize Bootstrap
I think the officially preferred way is now to use Less, and either dynamically override the bootstrap.css (using less.js), or recompile bootstrap.css (using Node or the Less compiler).
From the Bootstrap docs, here's how to override bootstrap.css styles dynamically:
Download the latest Less.js and include the path to it (and Bootstrap) in the <head>.
<link rel="stylesheet/less" href="/path/to/bootstrap.less">
<script src="/path/to/less.js"></script>
To recompile the .less files, just save them and reload your page. Less.js compiles them and stores them in local storage.
Or if you prefer to statically compile a new bootstrap.css with your custom styles (for production environments):
Install the LESS command line tool via Node and run the following command:
$ lessc ./less/bootstrap.less > bootstrap.css
Since Pabluez's answer back in December, there is now a better way to customize Bootstrap.
Use: Bootswatch to generate your bootstrap.css
Bootswatch builds the normal Twitter Bootstrap from the latest version (whatever you install in the bootstrap directory), but also imports your customizations. This makes it easy to use the the latest version of Bootstrap, while maintaining custom CSS, without having to change anything about your HTML. You can simply sway boostrap.css files.
You can use the bootstrap template from
http://www.initializr.com/
which includes all the bootstrap .less files. You can then change variables / update the less files as you want and it will automatically compile the css. When deploying compile the less file to css.
The best option in my opinion is to compile a custom LESS file including bootstrap.less, a custom variables.less file and your own rules :
Clone bootstrap in your root folder : git clone https://github.com/twbs/bootstrap.git
Rename it "bootstrap"
Create a package.json file : https://gist.github.com/jide/8440609
Create a Gruntfile.js : https://gist.github.com/jide/8440502
Create a "less" folder
Copy bootstrap/less/variables.less into the "less" folder
Change the font path : #icon-font-path: "../bootstrap/fonts/";
Create a custom style.less file in the "less" folder which imports bootstrap.less and your custom variables.less file : https://gist.github.com/jide/8440619
Run npm install
Run grunt watch
Now you can modify the variables any way you want, override bootstrap rules in your custom style.less file, and if some day you want to update bootstrap, you can replace the whole bootstrap folder !
EDIT: I created a Bootstrap boilerplate using this technique : https://github.com/jide/bootstrap-boilerplate
I recently wrote a post about how I've been doing it at Udacity for the last couple years. This method has meant we've been able to update Bootstrap whenever we wanted to without having merge conflicts, thrown out work, etc. etc.
The post goes more in depth with examples, but the basic idea is:
Keep a pristine copy of bootstrap and overwrite it externally.
Modify one file (bootstrap's variables.less) to include your own variables.
Make your site file #include bootstrap.less and then your overrides.
This does mean using LESS, and compiling it down to CSS before shipping it to the client (client-side LESS if finicky, and I generally avoid it) but it is EXTREMELY good for maintainability/upgradability, and getting LESS compilation is really really easy. The linked github code has an example using grunt, but there are many ways to achieve this -- even GUIs if that's your thing.
Using this solution, your example problem would look like:
Change the nav bar color with #navbar-inverse-bg in your variables.less (not bootstrap's)
Add your own nav bar styles to your bootstrap_overrides.less, overwriting anything you need to as you go.
Happiness.
When it comes time to upgrade your bootstrap, you just swap out the pristine bootstrap copy and everything will still work (if bootstrap makes breaking changes, you'll need to update your overrides, but you'd have to do that anyway)
Blog post with walk-through is here.
Code example on github is here.
Use LESS with Bootstrap...
Here are the Bootstrap docs for how to use LESS
(they have moved since previous answers)
you can start with this tool, https://themestr.app/theme , seeing how it overwrites the scss variables, you would get an idea what variable impacts what. its the simplest way I think.
example scss genearation:
#import url(https://fonts.googleapis.com/css?family=Montserrat:200,300,400,700);
$font-family-base:Montserrat;
#import url(https://fonts.googleapis.com/css?family=Open+Sans:200,300,400,700);
$headings-font-family:Open Sans;
$enable-grid-classes:false;
$primary:#222222;
$secondary:#666666;
$success:#333333;
$danger:#434343;
$info:#515151;
$warning:#5f5f5f;
$light:#eceeec;
$dark:#111111;
#import "bootstrap";

Resources