Bootstrap perhaps is the most popular frontend framework for developing mobile first projects on the web in recent years, its repository on github gets more than 100 thousands stars. Millions of websites are using it not only because it is easy to learn and use but the flexibility of customization. You can quickly start building a prototype or minimum viable product on the web by just including its 2 files (one is a CSS file and the other is a Javascript file), then do some customization later to make your web product stand out and look more professional.
In this book, we’ll focus on the customization part – build your own Bootstrap theme. At the time of writing this book, Bootstrap 4 is still in its alpha version, by “Bootstrap” here we are referring to Bootstrap 3. We will start with preparing a development workbench, and introducing Less (a CSS pre-processor Bootstrap uses), then walk through Bootstrap’s source code which will help us first get familiar with its code structure and later build themes by reusing it. Moreover, we will learn how to make additional styles and use plugins to polish our themes. Lastly we will touch on Bootstrap 4 a little and see how to use and customize it.
To learn something new, you need to practice, sometimes a lot. In this book I am following the “learn by doing” methodology: in most of chapters, I’ll put a “Practice” section. Usually those sections ask you to go to this book’s code repository (see the next section), open some files and learn the code inside. Some chapters will also contain a “Challenge” section, which will suggest you to make changes to the code we learned in that chapter. Those challenges usually are not hard to solve, and there for you to get your hands dirty, and help you have a better understanding.
This book is not an introduction to how to use Bootstrap, nor is it for learning the basics of HTML, CSS and Javascript, there are already plenty of awesome books on such fields. In general, I will assume that you have some working knowledge of HTML, CSS and using Bootstrap, for example you should be able to understand the following code:
{color:#295646;} bc. {color:#295646;}<div class="container container-fluid"> <div class="row"> <div class="col-xs-12 col-sm-10 col-md-8"> some article content ... </div> </div> </div> pre
You should know what
bc. {color:#295646;}container,
bc. {color:#295646;}col-xs-12 ,
bc. {color:#295646;}col-sm-10 classes mean in Bootstrap. If not, I suggest reading through some tutorials about using Bootstrap before coming back to this book. If you are already familiar with the basis of HTML, CSS and Bootstrap usage, and want to go further to customize its theme, or even sell your own theme in the marketplaces, this is the book for you.
Supplemental materials (code examples, exercises, etc) are available for download at: https://github.com/bofeng/make-bootstrap-themes
You should check the license before using the code examples and documentation. Usually it will not be a problem. Asking me for permission is not needed, but I do appreciate if you could include an attribution when using it, something like “From the book Make Bootstrap Themes By Bo Feng” would be great.
If you find errors in this book or the code example repository, you may create an issue ticket on the Github repository page:
https://github.com/bofeng/make-bootstrap-themes/issues
This book would not have been possible without the help and support of many others. Thank you to my reviewer, Sabrina Wagner, for your time and perceptive feedback. Thanks also to Xin Ge for his help with designing this great book cover.
And many thanks are owed to my dear friends Melora Loffreto, Devon Loffreto and my girlfriend Sherry. They put up with me throughout this process and provided moral support and guidance. Thank you.
First things first, let’s get our workbench ready. We need 4 items:
#
bc. {color:#295646;}http-server : it will help us easily setup a local web server.
#
bc. {color:#295646;}less : we use it to compile code written in Less to plain CSS, Bootstrap uses Less for generating its final CSS file. When we make our own themes, we will also write some code in Less, then use the
bc. {color:#295646;}lessc command to convert it to plain CSS. Don’t worry if you are not familiar with Less for now, we will learn more about it in chapter 2.
#
bc. {color:#295646;}Bootstrap source code : we will learn how Bootstrap organizes its code and this will teach us how to follow its structure and utilize its code to make our themes.
#
bc. {color:#295646;}theme-styles.html : we need to make a web page to view all commonly used Bootstrap components (typography, buttons, panels, alerts, etc). We will have all of them on one page so that we can easily see the changes when we make some customizations for our themes.
The first two items above are software applications, and we can install them through
bc. {color:#295646;}npm.
bc. {color:#295646;}npm comes along with the
bc. {color:#295646;}Node.js installation package, so we will first install
bc. {color:#295646;}Node.js. The third and fourth items are already included in the code repository for this book ( https://github.com/bofeng/make-bootstrap-themes ). You can clone it:
{color:#295646;} bc. {color:#295646;}$ git clone https://github.com/bofeng/make-bootstrap-themes.git pre
Or you can download the zipped file at following address, then unzip it:
https://github.com/bofeng/make-bootstrap-themes/archive/master.zip
Once you get it, in the folder you should be able to see the following files:
For writing convenience, in the following chapters, when we mention in the code repository or code repository folder, we are referring to this make-bootstrap-themes folder.
We will cover the installation both for Windows and macOS. Fortunately the process is quite straightforward using an installer package.
Installation steps:
Now let’s test if it works: go to any folder, (for example, your Download folder or the code repository folder make-bootstrap-themes), hold the shift key and right-click your mouse. In the pop-up menu, click Open command window here :
A command-line window will be opened up, then type two commands: use
bc. {color:#295646;}node -v first to see the Node.js version you have installed; then type
bc. {color:#295646;}npm -v to see the
bc. {color:#295646;}npm version. (Notice that
bc. {color:#295646;}npm is installed along with Node.js, and we will use
bc. {color:#295646;}npm to install other applications later).
Tips: When you type the
bc. {color:#295646;}node and
bc. {color:#295646;}npm commands in the command window, if an error like “command not found” shows up, try restarting your computer then running the commands again.
If you are using a Mac with macOS, the process is quite similar:
To test if it works, go to “Applications > Utilities“, open the “Terminal” application, and then type
bc. {color:#295646;}node -v and
bc. {color:#295646;}npm -v. You should be able to see the version they print out like below (depends on the version you installed, you may see a different version number):
{color:#295646;} bc. {color:#295646;}$ node -v v6.9.2 $ npm -v 3.10.9 pre
If you used this “Terminal” application a lot, and are familiar with many Linux/Unix commands like
bc. {color:#295646;}cd,
bc. {color:#295646;}ls, etc, you may jump to the Install http-server and Less section; if not, let’s do one more step, it will help you quickly open a “Terminal” inside one folder:
Let’s test it. Go find any folder (for example, your Desktop folder or the code repository folder make-bootstrap-themes), right-click on the folder, and in the pop-up menu, choose “New Terminal at Folder”. A Terminal will show up and its current directory is the folder you right-clicked, we will use this several times in the following chapters.
For writing convenience, in later content when we mention Open a command/terminal window at folder xxx, it means that, for a Windows user, go into this folder xxx, hold the shift key and right-click the mouse, and in the pop-up menu click “Open command window here”; for a macOS user, right-click on this folder xxx, and in the popup menu, click “New Terminal at Folder”.
Now that you have
bc. {color:#295646;}npm installed, we will now install
bc. {color:#295646;}http-server and
bc. {color:#295646;}less through one command. For Windows users, open a command/terminal window at any folder, then type:
{color:#295646;} bc. {color:#295646;}$ npm install http-server less -g pre
It may take several seconds, when it is done, we will have both
bc. {color:#295646;}http-server and
bc. {color:#295646;}less installed. Now let’s test if they work:
Let’s create a folder named test first, then create an index.html file under it, the file content could be really simple:
{color:#295646;} bc. {color:#295646;}<html> <body> Test http server </body> </html> pre
For Windows users, open a command window at this test folder, then simply type
bc. {color:#295646;}http-server. The system may show a prompt like below:
Click Allow access to continue, then the command window will show some information like this:
{color:#295646;} bc. {color:#295646;}Starting up http-server, serving ./ Available on: http://127.0.0.1:8080 ... pre
Since we just created an index.html file at this folder, and the http-server is serving this folder, now if we use browser to visit
bc. {color:#295646;}http://127.0.0.1:8080, the browser will open index.html file by default, we should be able to see the file content in the browser:
For macOS users, the process is quite similar. Open a terminal window at this test folder, then type
bc. {color:#295646;}http-server to start a web server, some information will show up:
{color:#295646;} bc. {color:#295646;}$ http-server Starting up http-server, serving ./ Available on: http://127.0.0.1:8080 ... pre
Now use a browser to visit
bc. {color:#295646;}http://127.0.0.1:8080, you should be able to see the page content.
When you run the
bc. {color:#295646;}http-server command in the command/terminal window, if it shows an error message like “Error: listen EADDRINUSE 0.0.0.0:8080”, this means the port number 8080 is taken by some other application, you can find the application to terminate it first, or, you can use a different port number by using the
bc. {color:#295646;}-p option, for example:
{color:#295646;} bc. {color:#295646;}$ http-server -p 4545 pre
The above command is using the port number 4545, but you can use other random numbers which roughly range from 2000 to 65,000. If no error shows up, visit
bc. {color:#295646;}http://127.0.0.1:4545, you should be able to see the page content.
The above
bc. {color:#295646;}npm install http-server less -g command also installs Less, a CSS pre-processor Bootstrap is using. What Less does basically is compiling the code written in Less syntax to plain CSS. Now let’s do a quick test to see if it works, don’t worry if you don’t understand the syntax of the following code, in chapter 2 we will learn more.
1) Create a
bc. {color:#295646;}test.less file at your test folder with the following code:
{color:#295646;} bc. {color:#295646;}@color: #ff6600; .mark { color: @color; } pre
2) Open a command/terminal window at this test folder, then use
bc. {color:#295646;}lessc command below to compile it:
{color:#295646;} bc. {color:#295646;}$ lessc test.less test.css pre
This will compile the Less code to plain CSS and save it in test.css file. Notice here we use
bc. {color:#295646;}lessc (there is an extra
bc. {color:#295646;}c at the end), which stands for less compiler.
3) Open this test.css file, it should contain the following code:
{color:#295646;} bc. {color:#295646;}.mark { color: #ff6600; } pre
If you are able to see the code in test.css, you have successfully installed Less.
Our theme-customization work will reuse some code from Bootstrap, so here we need to get its source code. If you downloaded the code repository for this book at the beginning of this chapter, it already includes the bootstrap-3.3.7 folder, so you are all set. Or if you want to download it separately, go to the following url to download the zip file and then unzip it:
https://github.com/twbs/bootstrap/archive/v3.3.7.zip
After unzipping it, you will have a [_ bootstrap-3.3.7_] folder. No matter which way you choose, under this folder you should be able to see a list of files like this:
When we are making a Bootstrap theme, a HTML page contains all the most commonly used Bootstrap components, like navbar, pager, panels, etc, which will help us quickly preview the changes and guide us for further customizations.
Here we name it theme-styles.html, and it contains the following components:
It’s a lot but don’t worry, I already put this theme-styles.html in the code repository. You can find it under the chapter1 folder. Again, if you still didn’t download the code repo, please do it.
Now let’s preview how this page looks.
Below are some screenshots of the theme-styles.html page, in your browser you should be able to see all the components.
Congratulations! We have completed setting up our workbench! Before we do the theme customizations part, we need to learn more about Less and Bootstrap’s code structure, which will be included in the next 2 chapters.
Less is a CSS pre-processor which allows us to make CSS more maintainable and extendable. Currently there are 2 popular CSS pre-processors – Sass and Less. The CSS part of Bootstrap 3 is written in Less. It also provides a Sass version, but you may need to download that separately. If you check Bootstrap’s source code folder bootstrap-3.3.7 which we downloaded in chapter 1.3, it already includes a folder named less, so here we will focus on introducing Less instead of Sass. While Bootstrap 4 uses Sass, in chapter 5 we will take a glance at Bootstrap 4 and learn more on Sass.
In this chapter we will go through some commonly used features of Less to get us prepared for the next customization step. If you are already familiar with Less, you can skip this chapter and move on to the next.
The “variable” feature allow us to define a variable then use it everywhere. If we want to change its value, we only need to do it in one place.
{color:#295646;} bc. {color:#295646;}@color: #ff6600;
.text-warn {
color: color;
}
.panel-warn {
color: #fff;
background-color:
color;
}
pre
Save it as test.less, then use the
bc. {color:#295646;}lessc command to compile it. If you forgot how to do this, go back to chapter 1.2 to review it.
{color:#295646;} bc. {color:#295646;}$ lessc test.less test.css pre
The above Less code will be compiled to plain CSS code and be saved in test.css file, it should have content like this:
{color:#295646;} bc. {color:#295646;}.text-warn { color: #ff6600; } .panel-warn { color: #fff; background-color: #ff6600; } pre
You can see each place with the
bc. {color:#295646;}@color variable are now replaced by its definition
bc. {color:#295646;}#ff6600. This makes it more convenient to change both the text color in
bc. {color:#295646;}.text-warn class and the background color in
bc. {color:#295646;}.panel-warn class, since we only need to change one place: the definition of the
bc. {color:#295646;}@color variable. For example, say we want to change it to
bc. {color:#295646;}@ee3300:
{color:#295646;} bc. {color:#295646;}@color: @ee3300; … pre
Both of the places will be replaced by this new value after compilation:
{color:#295646;} bc. {color:#295646;}.text-warn { color: #ee3300; } .panel-warn { color: #fff; background-color: #ee3300; } pre
Variables can also be used in selector names, property names, URLs and
bc. {color:#295646;}@import statements. We call this variable interpolation. The format is
bc. {color:#295646;}@{variable-name} , for example:
{color:#295646;} bc. {color:#295646;}@alertname: alert; @staticpath: "../static";
[email protected]{alertname}-info {
background-color: #339900;
}
[email protected]{alertname}-warn {
background-color: #ff6600;
}
.thumbup {
background: url(“@{staticpath}/img/thumbup.png”);
}
pre
After compilation:
{color:#295646;} bc. {color:#295646;}.alert-info { background-color: #339900; } .alert-warn { background-color: #ff6600; } .thumbup { background: url("../static/img/thumbup.png"); } pre
In this above example, since we defined
bc. {color:#295646;}@alertname to be
bc. {color:#295646;}alert, the class name
bc. {color:#295646;}[email protected]{alertname}-info becomes
bc. {color:#295646;}.alert-info with variable interpolation.
A variable can also be overridden. If we define one variable several times, only the last one is effective:
{color:#295646;} bc. {color:#295646;}@color: #ff6600;
.mark {
color: @color;
}
@color: #339900;
.info {
color: @color;
}
pre
After compilation:
{color:#295646;} bc. {color:#295646;}.mark { color: #339900; } .info { color: #339900; } pre
We can see that although we defined the
bc. {color:#295646;}.mark class before the second definition of the variable
bc. {color:#295646;}@color, both of the classes used the color
bc. {color:#295646;}#339900, which is the later one. Thus we can tell the compilation process is basically: Less first collects all of the variables, and during this process, one variable will override another if they have the same name. Then Less replaces all the places using that variable’s value.
This actually gives us the ability to override variables defined in Bootstrap’s source file. For example, Bootstrap has a variables.less file that defines almost all of the variables it uses, including font size, color, border color, etc. Thus we can redefine those variables’ values, and after recompilation, we will have a different theme with our customized variables. We will cover this more in chapter 3.
Another thing we should notice is that Less is a superset of CSS. We can write plain CSS code in a .less file, and it will generate the same content after compilation.
In plain CSS we can add comments by using
bc. {color:#295646;}/* … */. This is not very convenient when writing single-line comments. In Less we can use
bc. {color:#295646;}// to write single-line comments:
{color:#295646;} bc. {color:#295646;}/* Multiple lines comment are supported */ // headings // ————— @font-family-base: Arial, sans-serif; h1, h2, h3 { font-family: @font-family-base; color: #333; } pre
All of the single-line comments will be ignored during the compiling stage, the code above will be compiled to:
{color:#295646;} bc. {color:#295646;}/* Multiple lines comment are still supported */ h1, h2, h3 { font-family: Arial, sans-serif; color: #333; } pre
Notice in the generated CSS code,Less removes the single-line comments but keeps the multiple-line comments, since multiple-line comments are natively supported by plain CSS (CSS will ignore them after all), there is no need to remove them.
We can use arithmetical operators
bc. {color:#295646;}+ ,
bc. {color:#295646;}-,
bc. {color:#295646;}* ,
bc. {color:#295646;}/ on numbers and color codes. For example:
{color:#295646;} bc. {color:#295646;}@size: 14px; @width: 60%; @color: #ff6600;
.text-lg {
font-size: size * 2;
color:
color / 2;
}
.panel-lg {
width: width + 20;
color:
color – #112200;
}
pre
Compiled to:
{color:#295646;} bc. {color:#295646;}.text-lg { font-size: 28px; color: #803300; } .panel-lg { width: 80%; color: #ee4400; } pre
Suppose we have a
bc. {color:#295646;}
element). Commonly we write the CSS like this:
{color:#295646;} bc. {color:#295646;}.article { font-family: Arial, sans-serif; } .article > h3 { font-size: 1.4em; margin-bottom: 1.2em; } .article p { margin-bottom: 1.2em; } pre
This is for the
bc. {color:#295646;}h3 and
bc. {color:#295646;}p tags under the
bc. {color:#295646;}.article element. We may need to define several classes under this element, so we would need to add the
bc. {color:#295646;}.article prefix to all of them, which is not very convenient. Less provides a better way to do it:
{color:#295646;} bc. {color:#295646;}.article { font-family: Arial, sans-serif; > h3 { font-size: 1.4em; margin-bottom: 1.2em; } p { margin-bottom: 1.2em; } } pre
After complication:
{color:#295646;} bc. {color:#295646;}.article { font-family: Arial, sans-serif; } .article > h3 { font-size: 1.4em; margin-bottom: 1.2em; } .article p { margin-bottom: 1.2em; } pre
We can see it generates exactly the same code as we did before. In this way we not only write less code but we have a more clear structure.
For this nested rule, another common use case is the media-query, if we write the following code in Less:
{color:#295646;} bc. {color:#295646;}.lead { font-size: 16px; @media (min-width: 768px) { font-size: 20px; } } pre
After compilation:
{color:#295646;} bc. {color:#295646;}.lead { font-size: 16px; } @media (min-width: 768px) { .lead { font-size: 20px; } } pre
The Less processor generates the correct media-query code, and our Less version code is much more readable and organized than the plain CSS version. We can easily tell the rules inside
bc. {color:#295646;}.lead – generally set the font size to 16px, but change it to 20px for devices whose width is larger than 768px.
Mixins might be the most important feature in Less. If you are familiar with a programing language like Javascript, mixins are like self-defined functions:
{color:#295646;} bc. {color:#295646;}.bordered { border: 1px dotted black; } .panel { background: #e1e1e1; .bordered(); } pre
Compiled to:
{color:#295646;} bc. {color:#295646;}.bordered { border: 1px dotted black; } .panel { background: #e1e1e1; border: 1px dotted black; } pre
In the
bc. {color:#295646;}.panel class, we “invoke” the
bc. {color:#295646;}.bordered function, it will include all the code inside
bc. {color:#295646;}.bordered.
Mixins can also have parameters:
{color:#295646;} bc. {color:#295646;}.border-radius(@radius) { -webkit-border-radius: @radius; -moz-border-radius: @radius; border-radius: @radius; }
.btn {
font-size: 14px;
.border-radius(5px);
}
.panel {
.border-radius(8px);
}
pre
Compiled to:
{color:#295646;} bc. {color:#295646;}.btn { font-size: 14px; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } .panel { -webkit-border-radius: 8px; -moz-border-radius: 8px; border-radius: 8px; } pre
It can also have multiple parameters:
{color:#295646;} bc. {color:#295646;}.box(@margin, @padding) { margin: @margin; padding: @padding; }
.panel {
.box(3px, 5px);
}
.quote {
.box(5px, 10px);
}
pre
Compiled to:
{color:#295646;} bc. {color:#295646;}.panel { margin: 3px; padding: 5px; } .quote { margin: 5px; padding: 10px; } pre
We can group mixins together under a namespace. For example, if we want to make a mixin library for other developers to reuse, we can put our code under a namespace:
{color:#295646;} bc. {color:#295646;}#mbt-lib { .box(@background, @border, @text-color) { background-color: @background; border: 1px solid @border; color: @text-color; } } // use it .panel { #mbt-lib > .box(#f1f1f1, #cccccc, #555555); } pre
Compiled to:
{color:#295646;} bc. {color:#295646;}.panel { background-color: #f1f1f1; border: 1px solid #cccccc; color: #555555; } pre
We put a mixin named
bc. {color:#295646;}.box inside
bc. {color:#295646;}#mbt-lib. Other developers can use this mixin with
bc. {color:#295646;}#mbt-lib > .box, while they can still define their own
bc. {color:#295646;}.box mixin, and since our version
bc. {color:#295646;}.box is under the namespace
bc. {color:#295646;}#mbt-lib, those two
bc. {color:#295646;}.box functions would not conflict with each other.
Another use case would be putting all similar functions inside a group. For example, in Bootstrap’s source code, it defines several gradient mixins under the
bc. {color:#295646;}#gradient group.
{color:#295646;} bc. {color:#295646;}#gradient { .horizontal(@start-color, @end-color, @start-percent, @end-percent) { ... } .vertical(@start-color, @end-color, @start-percent, @end-percent) { ... } ... } pre
This
bc. {color:#295646;}#gradient group (or namespace) contains a horizontal gradient mixin and a vertical gradient mixin, for example our
bc. {color:#295646;}.panel will have a gradient background color by using the horizontal gradient mixin:
{color:#295646;} bc. {color:#295646;}.panel { ... #gradient > .horizontal(#555, #333, 0%, 100%); } pre
The
bc. {color:#295646;}& operator will refer to its parent selector, for example:
{color:#295646;} bc. {color:#295646;}.navbar { background: #333; &-default { .badge { background-color: #fff; } &:hover { background-color: #ff6600; } } } pre
Compiled to:
{color:#295646;} bc. {color:#295646;}.navbar { background: #333; } .navbar-default .badge { background-color: #fff; } .navbar-default:hover { background-color: #ff6600; } pre
The first
bc. {color:#295646;}& is replaced by its parent selector’s name
bc. {color:#295646;}.navbar. The second
bc. {color:#295646;}& is replaced by
bc. {color:#295646;}.navbar-default .
Another example:
{color:#295646;} bc. {color:#295646;}.input-sm { height: 30px; select& { line-height: 1.4em; } } pre
Compiled to :
{color:#295646;} bc. {color:#295646;}.input-sm { height: 30px; } select.input-sm { line-height: 1.4em; } pre
Also notice that when we use this
bc. {color:#295646;}& operator along with mixins, the code inside the mixin will first be included, and then do the
bc. {color:#295646;}& replacement. For example:
{color:#295646;} bc. {color:#295646;}.bg-warning { background-color: #ff9900; a&:hover, a&:focus { background-color: #ff3300; } }
.well {
.bg-warning();
}
pre
Compiled to:
{color:#295646;} bc. {color:#295646;}.bg-warning { background-color: #ff9900; } a.bg-warning:hover, a.bg-warning:focus { background-color: #ff3300; } .well { background-color: #ff9900; } a.well:hover, a.well:focus { background-color: #ff3300; } pre
We have the
bc. {color:#295646;}& operator in
bc. {color:#295646;}.bg-warning, so
bc. {color:#295646;}a.bg-warning:hover and
bc. {color:#295646;}a.bg-warning:focus are generated. In the
bc. {color:#295646;}.well class, we included this
bc. {color:#295646;}.bg-warning mixin, so the
bc. {color:#295646;}.well code will first become:
{color:#295646;} bc. {color:#295646;}.well { background-color: #ff9900; a&:hover, a&:focus { background-color: #ff3300; } } pre
Then the
bc. {color:#295646;}& sign will be replaced by its parent selector which is
bc. {color:#295646;}.well, thus we get
bc. {color:#295646;}a.well:hover and
bc. {color:#295646;}a.well:focus. Recall that the order is: first include the mixin, then do the
bc. {color:#295646;}& replacement. The order matters because if it is reversed, we will get
bc. {color:#295646;}.well a.bg-warning:hover and
bc. {color:#295646;}.well a.bg-warning:focus instead.
Suppose we have the following code:
{color:#295646;} bc. {color:#295646;}.navbar() { background: #333; &-default { .badge { background-color: #fff; } &:hover { background-color: #ff6600; } } }
.top {
&-nav {
.navbar();
}
}
pre
What code would it generate after compilation? Take a guess first, then compile it to see if your answer is correct:
Less provides a list of builtin functions. You can use them to do operations on strings, lists, do some math, change color values, etc. We are going to list the most commonly used functions here, since this is not a complete Less reference, but it should be enough for us to make a Bootstrap theme.
In Less, it is not uncommon to define font-size by using a base font size multiplying a decimal, for example, we may define our base font size as 14px, then for the
bc. {color:#295646;}h1 tag we use the font size as 2.2 times bigger; for the
bc. {color:#295646;}h2 we use 1.4 times bigger, etc. In this
bc. {color:#295646;}h2 case since 14 * 1.4 = 19.6, we may want to make it an integer. Depending on our use case, we may choose 19px or 20px. The
bc. {color:#295646;}floor and
bc. {color:#295646;}ceil functions can help us do the trick.
The
bc. {color:#295646;}floor function will round a number down to the next lowest integer. It will pick the closest integer which is less than or equal to the original number. If you are familiar with Javascript, this function does exactly the same thing as
bc. {color:#295646;}Math.floor in Javascript.
Example:
{color:#295646;} bc. {color:#295646;}small { font-size: floor(14px * 0.8); } h5 { font-size: floor(14px * 0.7); } h6 { font-size: floor(8.0px); } pre
In the above 3 cases:
So after compilation it becomes:
{color:#295646;} bc. {color:#295646;}small { font-size: 11px; } h5 { font-size: 9px; } h6 { font-size: 8px; } pre
This function will round a number up to the next highest integer. It will pick a closest integer which is greater than or equal to the original number. It does the same thing as
bc. {color:#295646;}Math.ceil in Javascript.
Example:
{color:#295646;} bc. {color:#295646;}big { font-size: ceil(14px * 1.2); } h4 { font-size: ceil(14px * 1.3); } h5 { font-size: ceil(12.0px); } pre
In the above 3 cases:
So after compilation it becomes:
{color:#295646;} bc. {color:#295646;}big { font-size: 17px; } h4 { font-size: 19px; } h5 { font-size: 12px; } pre
Less also provides a set of handy color operation functions.
This function increases the lightness of a color in the HSL color space by an absolute amount, we can think intuitively that it will make a color “brighter”.
This function takes 3 parameters:
For most use cases, you do not need the third parameter, here is an example:
{color:#295646;} bc. {color:#295646;}@default-link-color: #000000; @warning-link-color: #be4c0f;
a.default-link {
color: default-link-color;
}
a.default-link:hover {
color: lighten(
default-link-color, 28%);
}
a.warning-link {
color: warning-link-color;
}
a.warning-link:hover {
color: lighten(
warning-link-color, 15%);
}
pre
After compilation:
{color:#295646;} bc. {color:#295646;}a.default-link { color: #000000; } a.default-link:hover { color: #474747; }
a.warning-link {
color: #be4c0f;
}
a.warning-link:hover {
color: #ee6f2b;
}
pre
We can see the differences between before adding lightness and after:
The
bc. {color:#295646;}lighten function works like a charm, but you may wonder how it magically knows that changing our RGB color
bc. {color:#295646;}#be4c0f to
bc. {color:#295646;}#ee6f2b will make the color 15% brighter. The secret is that, when we pass an RGB hex value to this function, it will actually first convert the RGB value to the HSL color space, then increase a percentage on its lightness value, and then convert it back to the RGB space. Below is the pseudo code for this process:
{color:#295646;} bc. {color:#295646;}rgb = #be4c0f;
// convert RGB color to HSL color
hsl = convertRGBtoHSL(rgb);
// get hue, saturation, lightness channels of this color
h = getHueOfColor(hsl);
s = getSaturationOfColor(hsl);
l = getLightnessOfColor(hsl);
// increase the lightness channel’s value
l = l + 15%;
// now convert this new hsl value to RGB hex value
newRGB = convertHSLtoRGB(h, s, l);
// newRGB now is #ee6f2b
pre
Here is another example: we defined two classes,
bc. {color:#295646;}.color1 and
bc. {color:#295646;}.color2. In the
bc. {color:#295646;}.color1 code, we directly use the
bc. {color:#295646;}lighten function, while in
bc. {color:#295646;}.color2 we first convert RGB to HSL color space with the
bc. {color:#295646;}hue,
bc. {color:#295646;}saturation and
bc. {color:#295646;}lightness functions, then we increase the lightness channel’s value, and finally use the
bc. {color:#295646;}hsl function to convert this HSL color back to an RGB color. After compilation they produce the same color result.
{color:#295646;} bc. {color:#295646;}@mygreen: #80e619;
.color1 {
color: lighten(mygreen, 28%);
}
.color2 {
color: hsl(hue(
mygreen), saturation(mygreen), lightness(
mygreen) + 28);
}
pre
After compilation:
{color:#295646;} bc. {color:#295646;}.color1 { color: #c7f49a; } .color2 { color: #c7f49a; } pre
Notice that in the
bc. {color:#295646;}.color2 class, we utilized other color functions in Less:
*
bc. {color:#295646;}hue : Get the hue channel of a color object in the HSL color space.
*
bc. {color:#295646;}saturation : Get the saturation channel of a color object in the HSL color space.
*
bc. {color:#295646;}lightness : Get the lightness channel of a color object in the HSL color space.
*
bc. {color:#295646;}hsl : Creates an opaque color object from hue, saturation and lightness (HSL) values, output is an RGB hex number.
Converting an RGB color to the HSL color space requires some mathematical calculations. Since it is beyond the scope of this chapter, we won’t cover it here. If you are interested, I included some Javascript code doing the conversion in Appendix A: RGB and HSL color space conversions, from where you can see how the algorithm works.
The
bc. {color:#295646;}darken function does the reverse as
bc. {color:#295646;}lighten, it will decrease the lightness of a color. In the above example, after increasing the lightness of the color
bc. {color:#295646;}#80e619 by 28%, we get
bc. {color:#295646;}#c7f49a. If we decrease the lightness of this color
bc. {color:#295646;}#c7f49a by 28%, we can get the original color back:
{color:#295646;} bc. {color:#295646;}@mygreen: #80e619; @my-lightgreen: lighten(@mygreen, 28%); .color1 { color: @my-lightgreen; } .color2 { color: darken(@my-lightgreen, 28%); } pre
After compilation:
{color:#295646;} bc. {color:#295646;}.color1 { color: #c7f49a; } .color2 { color: #80e619; } pre
These 3 functions will correspondingly extract the
bc. {color:#295646;}red ,
bc. {color:#295646;}green,
bc. {color:#295646;}blue channel of a color, below is a common use case: we generate a half-transparent color of an existing color:
{color:#295646;} bc. {color:#295646;}@color: #ff6600; @color-half-alpha: rgba(red(@color), green(@color), blue(@color), .5);
.bg-warn {
color: @color-half-alpha;
}
pre
Compiled to:
{color:#295646;} bc. {color:#295646;}.bg-warn { color: rgba(255, 102, 0, 0.5); } pre
The
bc. {color:#295646;}fadein function increases the opacity of a color, if a color is already opaque, this function won’t affect it.
The code snippet below first defines a black color
bc. {color:#295646;}@inner-color with 0.2 alpha transparency, then defines another color
bc. {color:#295646;}@outer-color based on the first color with an increasing 60% opacity to make it more opaque. The third color
bc. {color:#295646;}@font-color is already an opaque color: it only has R, G, B value with no Alpha channel (or we can say its alpha value is 100% by default), so the
bc. {color:#295646;}fadein function will not have an effect on it even we write the code as increasing its opacity by 50%.
{color:#295646;} bc. {color:#295646;}@inner-color: rgba(0, 0, 0, 0.2); @outer-color: fadein(@inner-color, 60%); @font-color: #ff6600;
.popover {
background-color: inner-color;
border: 1px solid
outer-color;
color: fadein(@font-color, 50%);
}
pre
After compilation:
{color:#295646;} bc. {color:#295646;}.popover { background-color: rgba(0, 0, 0, 0.2); border: 1px solid rgba(0, 0, 0, 0.8); color: #ff6600; } pre
The
bc. {color:#295646;}fadeout function does the reverse of the
bc. {color:#295646;}fadein function: it decreases the opacity of a color, or we can say it increases the transparency of a color. Unlike
bc. {color:#295646;}fadein, it works on an opaque color, since an opaque color’s alpha value is 100%, and
bc. {color:#295646;}fadeout will decrease it.
{color:#295646;} bc. {color:#295646;}@font-color: #ff6600;
.popover {
color: fadeout(@font-color, 50%);
}
pre
After compilation:
{color:#295646;} bc. {color:#295646;}.popover { color: rgba(255, 102, 0, 0.5); } pre
The
bc. {color:#295646;}spin function rotates the hue angle of a color. The hue part of the HSL color space is a circle:
Say we have a yellow color, if we rotate it by -10 degrees, in the above picture it will go clockwise towards the red zone; if we rotate it by 10 degrees, it will go counter-clockwise towards the green zone.
For example, if you ever used the
bc. {color:#295646;}alert or
bc. {color:#295646;}alert-warning classes in Bootstrap before, your code looks like this:
{color:#295646;} bc. {color:#295646;}<div class="alert alert-warning"> <h4>Warning!</h4> <p>Warning message.</p> </div> pre
Under the default theme, this
bc. {color:#295646;}div looks like:
You can see the background and border have different colors. To generate the border color from the background color, Bootstrap uses this
bc. {color:#295646;}spin function along with the
bc. {color:#295646;}darken function, the code is defined like below:
{color:#295646;} bc. {color:#295646;}@alert-warning-bg: #fcf8e3; @alert-warning-border: darken(spin(@alert-warning-bg, -10), 5%); .alert-warning { background-color: @alert-warning-bg; border: 1px solid @alert-warning-border; // ... other properties } pre
After complication:
{color:#295646;} bc. {color:#295646;}.alert-warning { background-color: #fcf8e3; border: 1px solid #faebcc; // ... other properties } pre
We can see that to generate the border color, Bootstrap first spins the background color by -10 degrees (in the above hue picture, it will rotate this light yellow color
bc. {color:#295646;}#fcf8e3 towards the red zone by 10 degrees), then darkens this color by 5%. With these 2 steps we get a new color
bc. {color:#295646;}#faebcc. Bootstrap uses this trick for other alert states and panel states too, like
bc. {color:#295646;}.alert-success,
bc. {color:#295646;}.panel-warning,
bc. {color:#295646;}.panel-success, etc.
Go to repo’s folder chapter2/2.7, make some code changes in math.less and color.less, e.g. apply the
bc. {color:#295646;}floor,
bc. {color:#295646;}lighten,
bc. {color:#295646;}darken and
bc. {color:#295646;}fadein functions to some value, then use
bc. {color:#295646;}lessc to compile it to see how those values change.
The extend pseudo class can merge the selector in which it is located with the one that it references. For example:
{color:#295646;} bc. {color:#295646;}.btn { background-color: #ff6600; color: #ffffff; } .btn-large { &:extend(.btn); padding: 5px 10px; font-size: 18px; } pre
Outputs after compilation:
{color:#295646;} bc. {color:#295646;}.btn, .btn-large { background-color: #ff6600; color: #ffffff; } .btn-large { padding: 5px 10px; font-size: 18px; }
pre
See now the
bc. {color:#295646;}.btn-large class also has the CSS rule set as the
bc. {color:#295646;}.btn class.
If we have nested selectors, by default the
bc. {color:#295646;}&:extend directive won’t extend them. Example:
{color:#295646;} bc. {color:#295646;}.header { padding: 10px; h3 { color: #fff; } }
.nav-top {
&:extend(.header);
}
pre
After compilation:
{color:#295646;} bc. {color:#295646;}.header, .nav-top { padding: 10px; } .header h3 { color: #fff; } pre
We can see the
bc. {color:#295646;}.nav-top class now has the
bc. {color:#295646;}padding: 10px rule, but the
bc. {color:#295646;}h3 is ignored. If we want to include all of the nested selectors, we need to add the
bc. {color:#295646;}all keyword.
{color:#295646;} bc. {color:#295646;}.header { padding: 10px; h3 { color: #fff; } }
.nav-top {
&:extend(.header all);
}
pre
Compiled to:
{color:#295646;} bc. {color:#295646;}.header, .nav-top { padding: 10px; } .header h3, .nav-top h3 { color: #fff; } pre
Now we have both of the
bc. {color:#295646;}.nav-top and
bc. {color:#295646;}.nav-top h3 selectors.
In our first
bc. {color:#295646;}.btn and
bc. {color:#295646;}.btn-large example, you may have noticed that we can achieve the same result by using mixins:
{color:#295646;} bc. {color:#295646;}.btn { background-color: #ff6600; color: #ffffff; } .btn-large { .btn(); padding: 5px 10px; font-size: 18px; } pre
Notice that we use
bc. {color:#295646;}.btn() to replace
bc. {color:#295646;}&:extend(.btn), and after compilation it becomes this:
{color:#295646;} bc. {color:#295646;}.btn { background-color: #ff6600; color: #ffffff; } .btn-large { background-color: #ff6600; color: #ffffff; padding: 5px 10px; font-size: 18px; } pre
Now the
bc. {color:#295646;}.btn-large also has the rule set defined in
bc. {color:#295646;}.btn class, so if we can use mixins to do the same thing, why and when should we use
bc. {color:#295646;}&:extend?
Well, if we check the generated code in plain CSS, we can see by using
bc. {color:#295646;}&:extend we will have less code than using mixins. Generally because mixins copy the same CSS rule set in the place that calls it, while
bc. {color:#295646;}&:extend combines the selectors instead of doing code replication. So yes, using
bc. {color:#295646;}&:extend will help us remove unnecessary duplication and reduce the final CSS size, but does that mean we should always choose
bc. {color:#295646;}&:extend over mixins?
Let’s see another example:
{color:#295646;} bc. {color:#295646;}.base-font { font-family: Arial, Verdana, sans-serif; color: #000; }
h1 {
&:extend(.base-font);
font-size: 2em;
}
.panel-warning {
&:extend(.base-font);
background-color: #ff9900;
color: #fff;
}
.alert-danger {
&:extend(.base-font);
background-color: #ff3300;
color: #fff;
}
pre
We have a
bc. {color:#295646;}.base-font class which defined the font type and color, the other 3 selectors
bc. {color:#295646;}h1,
bc. {color:#295646;}.panel-warning and
bc. {color:#295646;}.alert-danger are using
bc. {color:#295646;}&:extend to use the CSS rule set in
bc. {color:#295646;}.base-font.
After compilation:
{color:#295646;} bc. {color:#295646;}.base-font, h1, .panel-warning, .alert-danger { font-family: Arial, Verdana, sans-serif; color: #000; } h1 { font-size: 2em; } .panel-warning { background-color: #ff9900; color: #fff; } .alert-danger { background-color: #ff3300; color: #fff; } pre
It clearly generates less code than using mixins like
bc. {color:#295646;}.base-font(), however, in the first part of the compiled CSS, while we let
bc. {color:#295646;}.base-font,
bc. {color:#295646;}h1,
bc. {color:#295646;}.panel-warning and
bc. {color:#295646;}.alert-danger share the same CSS rule set, they do not have any relationships. The code is a little confusing when we put those 4 selectors together to share a rule set, because it is like we are forcing a parallel relationship between those 4 unrelated selectors. However, our first
bc. {color:#295646;}.btn and
bc. {color:#295646;}.btn-large example is a great case to use
bc. {color:#295646;}&:extend, since
bc. {color:#295646;}.btn-large is a button (just a larger version), it has a relationship with
bc. {color:#295646;}.btn.
So when do we use
bc. {color:#295646;}&:extend and when do we use mixins? Personally I prefer to use
bc. {color:#295646;}&:extend when there is an
bc. {color:#295646;}is-a relationship between selectors, while I use mixins when there is a
bc. {color:#295646;}has-a relationship. For example,
bc. {color:#295646;}.btn-large “is-a”
bc. {color:#295646;}.btn, so we use
bc. {color:#295646;}&:extend;
bc. {color:#295646;}.panel-warning is not a
bc. {color:#295646;}.base-font, but “has-a”
bc. {color:#295646;}.base-font, so we should use
bc. {color:#295646;}.base-font(). In conclusion, though
bc. {color:#295646;}&:extend can generate less code, it doesn’t mean we should use it everywhere, we choose one over the other depends on the relationships they have to keep the generated CSS code readable and organized.
In plain CSS we use the
bc. {color:#295646;}@import directive to import style rules from other style sheets like:
{color:#295646;} bc. {color:#295646;}@import url("fineprint.css"); @import "custom.css"; pre
This
bc. {color:#295646;}@import in Less does about the same, but unlike in plain CSS where we have to put it ahead of all other types of rules, in Less we can put it anywhere in the file.
{color:#295646;} bc. {color:#295646;}.text-warning { color: #ff6600; } @import "my-mixins.less"; pre
We can also omit the .less suffix:
{color:#295646;} bc. {color:#295646;}@import "my-mixins.less"; // next line does the same thing @import "my-mixins" pre
If several files import the same file, by default, this file will only be included once. Suppose we have 3 files here:
color.less:
{color:#295646;} bc. {color:#295646;}.text-warning { color: #ff6600; } pre
In next box.less file, we import this color.less :
{color:#295646;} bc. {color:#295646;}@import "color"; .box-warning { .text-warning; } pre
We also include color.less in another file container.less:
{color:#295646;} bc. {color:#295646;}@import "color"; @import "box"; .panel-warning { .text-warning; } pre
As shown below, color.less is included twice (directly and indirectly) in container.less:
Now if we compile container.less, we will have:
{color:#295646;} bc. {color:#295646;}.text-warning { color: #ff6600; } .box-warning { color: #ff6600; } .panel-warning { color: #ff6600; } pre
We can see that although color.less is included twice, the final generated CSS code only contains the
bc. {color:#295646;}.text-warning class once.
This is also the default behavior of the
bc. {color:#295646;}@import directive but we can change it. If we want to include the same file multiple time, in container.less we can use:
{color:#295646;} bc. {color:#295646;}@import (multiple) "color"; @import (multiple) "box"; pre
After compilation,
bc. {color:#295646;}.text-warning will be included twice:
{color:#295646;} bc. {color:#295646;}.text-warning { color: #ff6600; } .text-warning { color: #ff6600; } .box-warning { color: #ff6600; } .panel-warning { color: #ff6600; } pre
Less support 7 types of import options, including reference, inline, less, css, once, multiple and optional, we have seen two of them, once (the default behavior) and multiple. For most cases, the default one should work well, if you want to check other 5 types, go to http://lesscss.org/features/#import-options for more details.
In the above
bc. {color:#295646;}@import code in container.less, we either use the multiple keyword for both lines:
{color:#295646;} bc. {color:#295646;}@import (multiple) "color"; @import (multiple) "box"; pre
Or both without it:
{color:#295646;} bc. {color:#295646;}@import "color"; @import "box"; pre
What if we use multiple only for one line like this:
{color:#295646;} bc. {color:#295646;}@import "color"; @import (multiple) "box"; pre
What would the CSS code be after we compile it? Now try it yourself:
In the generated code, how many times the
bc. {color:#295646;}.text-warning class appears?
Further more, what happens if we change
bc. {color:#295646;}multiple to
bc. {color:#295646;}reference ?
{color:#295646;} bc. {color:#295646;}@import (reference) "color"; @import (reference) "box"; pre
Now it’s time to do the customization part of making our own themes. To make a Bootstrap theme, essentially we are overriding its current CSS rules. For example, if we use Bootstrap’s
bc. {color:#295646;}.btn-warning class on a button:
{color:#295646;} bc. {color:#295646;}<button class="btn btn-warning">Warning</button> pre
Under its default theme, this button has a yellow-like background, the font size inside the button is 14px and its text color is white. If we want to customize it, we add another CSS rule to override it like this:
{color:#295646;} bc. {color:#295646;}.btn { font-size: 16px; } .btn-warning { background-color: #a442f4; } pre
This will change the button’s background color to purple and the font size to 16px.
This is a key part of making a Bootstrap theme: we include Bootstrap’s default CSS ruleset, and we add more CSS rules to override some of them, then we will have our own theme.
Now suppose we want to change the navigation bar’s style, we need to override some of the CSS rules for it. How many of those rules do we need? What are they? To answer these questions, it would be better first to dive into Bootstrap’s source code, know how Bootstrap’s CSS is organized, and then we will have a clear picture.
In chapter 1 we downloaded the source code of bootstrap-3.3.7 (or you can find it in the code repo), it includes several folders and files:
All other files are related to building or managing Bootstrap package, so we can ignore them for now. What we really need here is the less folder. We need to know how Bootstrap organizes its CSS code, then our customization needs to reuse some code from it. In this section we will mainly focus on the less folder.
Under this less folder, there are 41 .less files and one mixins folder. We can roughly split these to 4 parts:
Let’s start with bootstrap.less. This file is used for generating Bootstrap CSS for the default theme. Let’s test it now:
First go to the folder bootstrap-3.3.7/less, and start a command/terminal window there. Then in the command/terminal window, type :
{color:#295646;} bc. {color:#295646;}$ lessc bootstrap.less bootstrap.css pre
It may take 1 or 2 seconds but when it is finished, we will have a new file named bootstrap.css inside the less folder. This means we just generated Bootstrap’s CSS file from its source code.
Recall in chapter 1 we created a theme-styles.html file, and in that file we link the CSS from Bootstrap’s dist folder like this:
{color:#295646;} bc. {color:#295646;}<link rel="stylesheet" href="/bootstrap-3.3.7/dist/css/bootstrap.css"/> pre
Let’s change it to our own compiled version: first go to the code repository folder chapter3/3.1, then open the file theme-styles.html in that folder. At around line #5 change the CSS link from
bc. {color:#295646;}/bootstrap-3.3.7/dist/css/bootstrap.css to
bc. {color:#295646;}/bootstrap-3.3.7/less/bootstrap.css :
{color:#295646;} bc. {color:#295646;}<link rel="stylesheet" href="/bootstrap-3.3.7/less/bootstrap.css"/> pre
Start a command/terminal window at the repository root folder make-bootstrap-themes, then type
bc. {color:#295646;}http-server to start a web server. Now visit theme-styles.html page at: http://127.0.0.1:8080/chapter3/3.1/theme-styles.html . This page should now look exactly the same as before, which means our self-compiled Bootstrap CSS works!
Now let’s try Bootstrap’s alternative theme using the theme.less file. At folder bootstrap-3.3.7/less start a command/terminal window, then type the following command to compile it to a plain CSS file:
{color:#295646;} bc. {color:#295646;}$ lessc theme.less theme.css pre
Then in theme-styles.html file, add another line to link to this theme CSS file:
{color:#295646;} bc. {color:#295646;}<link rel="stylesheet" href="/bootstrap-3.3.7/less/bootstrap.css"/> <link rel="stylesheet" href="/bootstrap-3.3.7/less/theme.css"/> ... pre
Now refresh theme-styles.html page at http://127.0.0.1:8080/chapter3/3.1/theme-styles.html. Do you see the changes? For example, all the buttons now have gradient color, so our self-compiled theme CSS works!
Now back to the other .less files under [_ bootstrap-3.3.7/less_]. If we check the source code in bootstrap.less, we can see that it uses the
bc. {color:#295646;}@import command to include all of the other 39 .less files, and all of those 39 files can be divided into 4 categories:
This group of files defines the basic classes, including typography, grid system, tables, forms,etc.
This group of files defines the CSS for components, like button groups, navigation bar, etc, the file names are quite straightforward:
Those components usually are being used with Javascript. For example, when a user clicks a button, it may open up a modal or a tooltip component:
These 2 files below define some utility classes, and in most scenarios we don’t need to change them when making themes.
Find one component file, e.g. alerts.less, and check the source code to see how Bootstrap defines its classes in Less. Then try to answer the following questions:
We just learned Bootstrap’s code structure, so going back to the question at the beginning of this chapter: if we want to change the navigation bar’s style, we need to override some of styles, but what specific classes do we need to override?
Say we want to change the navigation bar to the following styles:
In the previous section, we mentioned that navbar.less defines the CSS for the navigation bar, so we need to check this file and find the CSS rules to override. It contains around 650 lines code but for our modifications, we only need to examine
bc. {color:#295646;}.navbar,
bc. {color:#295646;}.navbar-default, and the
bc. {color:#295646;}.navbar-inverse parts.
Let’s create a my-navbar.less file. For the first 2 changes listed above, we want to override the
bc. {color:#295646;}.navbar class, so let’s put the following content in our my-navbar.less file:
{color:#295646;} bc. {color:#295646;}.navbar { border-radius: 0; border: none; } pre
We set the border radius to be 0 to remove the rounded corners, and set border to none to remove its default 1px border. Next we want to add a 2px border at bottom for both
bc. {color:#295646;}.navbar-default and
bc. {color:#295646;}.navbar-inverse, since they are using different colors. Let’s define colors first:
{color:#295646;} bc. {color:#295646;}@navbar-default-border-color: #70A1D7; @navbar-inverse-border-color: #F35B25; pre
Then we define the bottom border for both
bc. {color:#295646;}.navbar-default and
bc. {color:#295646;}.navbar-inverse
{color:#295646;} bc. {color:#295646;}.navbar-default { border-bottom: 2px solid @navbar-default-border-color; } .navbar-inverse { border-bottom: 2px solid @navbar-inverse-border-color; } pre
Now let’s change the active navigation item’s style. Again, check the code in navbar.less. We can see that the .navbar-default class defines a sub class .navbar-nav inside it:
{color:#295646;} bc. {color:#295646;}.navbar-nav { > li > a { color: @navbar-default-link-color; &:hover, &:focus { color: @navbar-default-link-hover-color; background-color: @navbar-default-link-hover-bg; } } > .active > a { &, &:hover, &:focus { color: @navbar-default-link-active-color; background-color: @navbar-default-link-active-bg; } } > .disabled > a { &, &:hover, &:focus { color: @navbar-default-link-disabled-color; background-color: @navbar-default-link-disabled-bg; } } } pre
It has the styles for a navigation item’s normal state, active state, and disabled state. In our case, to override the style for the active state, we only need to change the
bc. {color:#295646;}> .active > a part. Let’s add this to our
bc. {color:#295646;}.navbar-default and
bc. {color:#295646;}.navbar-inverse:
{color:#295646;} bc. {color:#295646;}.navbar-default { border-bottom: 2px solid @navbar-default-border-color; .navbar-nav { > .active > a { &, &:hover, &:focus { color: #fff; background-color: @navbar-default-border-color; } } } }
.navbar-inverse {
border-bottom: 2px solid navbar-inverse-border-color;
.navbar-nav {
> .active > a {
&, &:hover, &:focus {
color: #fff;
background-color:
navbar-inverse-border-color;
}
}
}
}
pre
Notice we nest
bc. {color:#295646;}.navbar-nav in the
bc. {color:#295646;}.navbar-default and the
bc. {color:#295646;}.navbar-inverse classes, and inside this
bc. {color:#295646;}.navbar-nav class, we nest
bc. {color:#295646;}> .active > a. Inside this
bc. {color:#295646;}a, we again nest the
bc. {color:#295646;}&, &:hover, &:focus classes, and then under this rule we set the font color and the background color.
Now our my-navbar.less file has 4 parts:
*
bc. {color:#295646;}.navbar class
*
bc. {color:#295646;}.navbar-default class
*
bc. {color:#295646;}.navbar-inverse class
Let’s compile the Less code to plain CSS:
{color:#295646;} bc. {color:#295646;}$ lessc my-navbar.less my-navbar.css pre
After compilation:
{color:#295646;} bc. {color:#295646;}.navbar { border-radius: 0; border: none; } .navbar-default { border-bottom: 2px solid #70A1D7; } .navbar-default .navbar-nav > .active > a, .navbar-default .navbar-nav > .active > a:hover, .navbar-default .navbar-nav > .active > a:focus { color: #fff; background-color: #70A1D7; } .navbar-inverse { border-bottom: 2px solid #F35B25; } .navbar-inverse .navbar-nav > .active > a, .navbar-inverse .navbar-nav > .active > a:hover, .navbar-inverse .navbar-nav > .active > a:focus { color: #fff; background-color: #F35B25; } pre
Add this compiled
bc. {color:#295646;}my-navbar.css to the theme-styles.html:
{color:#295646;} bc. {color:#295646;}<link rel="stylesheet" href="path/to/my-navbar.css"/> pre
Refresh page we can see the changes.
Can you add styles in my-navbar.less for the alert badges to change its background color? After you make the change, remember to use
bc. {color:#295646;}lessc to recompile it, then refresh the navbar.html page.
Hint: You can add a
bc. {color:#295646;}.badge class inside both the
bc. {color:#295646;}.navbar-default and the
bc. {color:#295646;}.navbar-inverse classes.
Recall in the last section we saw Bootstrap’s
bc. {color:#295646;}.navbar-nav source code like this:
{color:#295646;} bc. {color:#295646;}.navbar-nav { > .active > a { &, &:hover, &:focus { color: @navbar-default-link-active-color; background-color: @navbar-default-link-active-bg; } } } pre
You may have noticed that under the
bc. {color:#295646;}.navbar-nav selector, Bootstrap is using two variables
bc. {color:#295646;}@navbar-default-link-active-color and
bc. {color:#295646;}@navbar-default-link-active-bg to set the font color and background color for the active state, and their values are actually defined in Bootstrap’s variables.less code as a gray color like
bc. {color:#295646;}#555555. That’s why in Bootstrap’s default theme, the background color of the default navbar is gray. This gives us a hint: to achieve the same customizations as we did in the last section, can we just change the values of these 2 variables and recompile bootstrap.less file to generate a new CSS file? Then using this new CSS file, our navigation bar’s font color and background color should be changed, right?
The answer is yes, and this might be the easiest way to make a bootstrap theme. Also the good news is we already knew the key part: in chapter 2 we learned in Less we can override some variables (if two variables have the same name, the later one’s value will override former one’s), and in section 3.1 we learned how to use the
bc. {color:#295646;}lessc command to compile
bc. {color:#295646;}bootstrap.less to a plain CSS file, so to make our own theme, one method is:
Let’s do a quick test for our navigation bar to see if we can achieve the same result as we did in the last section:
1) Create a file named my-variables.less. Inside it we redefine some variables related to the navigation bar. In our case, we want to remove the border radius, and also override the active navigation item’s font and background color for both
bc. {color:#295646;}.navbar-default and
bc. {color:#295646;}.navbar-inverse. In Bootstrap’s source code file navbar.less, under the
bc. {color:#295646;}.navbar selector:
{color:#295646;} bc. {color:#295646;}.navbar { ... @media (min-width: @grid-float-breakpoint) { border-radius: @navbar-border-radius; } } pre
It is using the
bc. {color:#295646;}@navbar-border-radius variable to define the navigation bar’s border radius, which means we can remove the border radius by redefining this variable’s value to 0. We also mentioned that under the
bc. {color:#295646;}.navbar-default .navbar-nav selector 2 variables are being used:
bc. {color:#295646;}@navbar-default-link-active-color and
bc. {color:#295646;}@navbar-default-link-active-bg, and for the
bc. {color:#295646;}.navbar-inverse .navbar-nav selector, there are another 2 variables:
bc. {color:#295646;}@navbar-inverse-link-active-color and
bc. {color:#295646;}@navbar-inverse-link-active-bg. So we need to override those 5 variables’ values. Let’s put the following 5 lines in the my-variables.less file:
{color:#295646;} bc. {color:#295646;}@navbar-border-radius: 0; @navbar-default-link-active-color: #fff; @navbar-default-link-active-bg: #70A1D7; @navbar-inverse-link-active-color: #fff; @navbar-inverse-link-active-bg: #F35B25; pre
2) Create the file my-theme.less. First import bootstrap.less then import my-variables.less (notice the order matters here, since the latter one overrides the former one’s variables, in our case we want the variables defined in my-variables.less to override the ones in bootstrap.less). We will also add code for
bc. {color:#295646;}.navbar to add a 2px border at bottom, and use different border colors for
bc. {color:#295646;}.navbar-default and
bc. {color:#295646;}.navbar-inverse:
{color:#295646;} bc. {color:#295646;}@import "path/to/bootstrap-3.3.7/less/bootstrap.less"; @import "my-variables.less";
.navbar {
border: none;
border-bottom: 2px solid transparent;
&-default {
border-bottom-color: navbar-default-link-active-bg;
}
&-inverse {
border-bottom-color:
navbar-inverse-link-active-bg;
}
}
pre
3) Compile my-theme.less to generate the CSS file my-theme.css:
{color:#295646;} bc. {color:#295646;}$ lessc my-theme.less my-theme.css pre
This my-theme.less file imported bootstrap.less, so after compilation my-theme.css will contain all of the CSS code of Bootstrap’s default theme, plus the customization code for the navigation bar.
4) Replace the link to the Bootstrap CSS file to our own my-theme.css (notice if your my-theme.css is located in a different path, make sure you use the right value for the
bc. {color:#295646;}href attribute) :
{color:#295646;} bc. {color:#295646;}<link rel="stylesheet" href="path/to/bootstrap-3.3.7/dist/css/bootstrap.css"/> pre
Replaced by:
{color:#295646;} bc. {color:#295646;}<link rel="stylesheet" href="path/to/my-theme.css"/> pre
Now refresh this page. We should be able to see the style changes in the navigation bar.
Visit http://127.0.0.1:8080/chapter3/3.3/navbar.html again. Since it is using my-theme.css now, the navigation bar should be changed like this:
Open my-theme.less and view the source code. Can you add some code to change the alert badge’s background color for both
bc. {color:#295646;}.navbar-default and
bc. {color:#295646;}.navbar-inverse?
Hint: you can add
bc. {color:#295646;}.badge class in both
bc. {color:#295646;}&-default and
bc. {color:#295646;}&-inverse selectors.
Those 5 variables we defined in my-variables.less are originally defined in Bootstrap’s variables.less file, and around 387 variables are defined there in total.
We know those 5 variables are only related to the navigation bar, so to customize all of components in theme-styles.html, including typography, buttons, panels, etc., we need to override more variables. It’s better to first get to know what those variables are in variables.less and what they are used for.
The file variables.less groups those 387 variables into around 35 sections, from the basic font styles, brand colors to variables of components, including buttons, form controls, grid system, containers, navigation bars, etc. For example, we can find variables defined for the navigation bar in the
bc. {color:#295646;}navbar section:
{color:#295646;} bc. {color:#295646;}... @navbar-default-color: #777; @navbar-default-bg: #f8f8f8; @navbar-default-border: darken(@navbar-default-bg, 6.5%);
// Navbar links
navbar-default-link-color: #777;
navbar-default-link-hover-color: #333;
navbar-default-link-hover-bg: transparent;
navbar-default-link-active-color: #555;
navbar-default-link-active-bg: darken(
navbar-default-bg, 6.5%);
navbar-default-link-disabled-color: #ccc;
navbar-default-link-disabled-bg: transparent;
// Navbar brand label
navbar-default-brand-color:
navbar-default-link-color;
navbar-default-brand-hover-color: darken(
navbar-default-brand-color, 10%);
@navbar-default-brand-hover-bg: transparent;
…
pre
The code is well organized. If we want to customize a component, we can easily find it in the corresponding section and then override its variables in our own my-variables.less. We won’t go through all the variables because that would be too many, but there are 6 sections we need to pay attention to, since those variables define the basic styles, and are widely used by components.
There are 6 levels of gray colors defined, they are all based on
bc. {color:#295646;}@gray-base color:
{color:#295646;} bc. {color:#295646;}@gray-base: #000; @gray-darker: lighten(@gray-base, 13.5%); // #222 @gray-dark: lighten(@gray-base, 20%); // #333 @gray: lighten(@gray-base, 33.5%); // #555 @gray-light: lighten(@gray-base, 46.7%); // #777 @gray-lighter: lighten(@gray-base, 93.5%); // #eee pre
Among those 6 variables,
bc. {color:#295646;}@gray-darker is not being used in any of Bootstrap’s .less files; the
bc. {color:#295646;}@gray-dark and the
bc. {color:#295646;}@gray colors are generally used for common text color;
bc. {color:#295646;}@gray-light and
bc. {color:#295646;}@gray-lighter are widely used for background color and the mouse hover color.
This section defines 5 contextual colors:
{color:#295646;} bc. {color:#295646;}@brand-primary: darken(#428bca, 6.5%); // #337ab7 @brand-success: #5cb85c; @brand-info: #5bc0de; @brand-warning: #f0ad4e; @brand-danger: #d9534f; pre
Lots of components use those for their own contextual colors. For example, the button’s class
bc. {color:#295646;}.btn-primary uses
bc. {color:#295646;}@brand-primary as background color,
bc. {color:#295646;}.btn-success uses
bc. {color:#295646;}@brand-success as background color;
bc. {color:#295646;}.label-warning uses
bc. {color:#295646;}@brand-warning as background color;
bc. {color:#295646;}.progress-bar-danger uses
bc. {color:#295646;}@brand-danger as background color, etc.
This section defines variables for some global styles. For example, the page body’s background color, the common text color, and a link’s normal state color and hover state color.
{color:#295646;} bc. {color:#295646;}@body-bg: #fff; @text-color: @gray-dark; @link-color: @brand-primary; @link-hover-color: darken(@link-color, 15%); @link-hover-decoration: underline; pre
This section defines basic font styles, including font family, font size, line height, etc.
{color:#295646;} bc. {color:#295646;}@font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif; @font-family-base: @font-family-sans-serif; @font-size-base: 14px; @line-height-base: 1.428571429; ... pre
This section defines common styles for components, including paddings, border radius, text and background color of active state, etc.
{color:#295646;} bc. {color:#295646;}@padding-base-vertical: 6px; @padding-base-horizontal: 12px; @border-radius-base: 4px; @border-radius-large: 6px; @component-active-bg: @brand-primary; ... pre
For example, the border radius variables are used by almost all components, including buttons, form inputs, navigation bar, progress bar, panels and wells, etc.
The brand contextual colors section above defines one group of contextual colors, this section defines another group.
{color:#295646;} bc. {color:#295646;}@state-success-text: #3c763d; @state-success-bg: #dff0d8; @state-success-border: darken(spin(@state-success-bg, -10), 5%); @state-info-text: #31708f; @state-info-bg: #d9edf7; @state-info-border: darken(spin(@state-info-bg, -10), 7%); @state-warning-text: #8a6d3b; @state-warning-bg: #fcf8e3; @state-warning-border: darken(spin(@state-warning-bg, -10), 5%); @state-danger-text: #a94442; @state-danger-bg: #f2dede; @state-danger-border: darken(spin(@state-danger-bg, -10), 5%); pre
Bootstrap’s alert and panel components use those variables. For example,
bc. {color:#295646;}.alert-warning uses
bc. {color:#295646;}@state-warning-text as text color,
bc. {color:#295646;}@state-warning-bg as background color, and
bc. {color:#295646;}@state-warning-border as border color.
Since those variables in the above 6 sections are widely used across all of components, we can just change those variables to get a customized theme. We will try this method in next section.
To choose which variable to override, usually some design work is involved: first pick some colors as the theme colors, then use software like Photoshop or Illustrator to draw the web page or components. During the process maybe some colors may need to be adjusted. Once you have finished the design, choose variables to override to make this theme. However, since this is not a design book, let’s simplify the process by focusing on the following questions:
For our first theme, I want to keep it simple, here are my choices:
Let’s start coding this new my-variables.less, the first part is using the Nunito font as our default font-family:
{color:#295646;} bc. {color:#295646;}@font-family-sans-serif: Nunito, Helvetica, Arial, sans-serif; @headings-font-weight: 700; pre
Here we also override the headings font weight to 700, because the weight of bold font in Nunito is 700, while the value is 500 by default in Bootstrap’s variables.less file.
Next, let’s define the brand contextual and state contextual colors:
{color:#295646;} bc. {color:#295646;}// brand contextual colors @brand-primary: #3B4A6B; @brand-success: #52D681; @brand-info: #22B2DA; @brand-warning: #FFC24A; @brand-danger: #F23557;
// state contextual colors
state-success-text:
brand-success;
state-success-bg: lighten(
state-success-text, 40%);
state-success-border:
state-success-text;
state-info-text:
brand-info;
state-info-bg: lighten(
state-info-text, 45%);
state-info-border:
state-info-text;
state-warning-text:
brand-warning;
state-warning-bg: lighten(
state-warning-text, 34%);
state-warning-border:
state-warning-text;
state-danger-text:
brand-danger;
state-danger-bg: lighten(
state-danger-text, 40%);
state-danger-border:
state-danger-text;
pre
Notice here for the state contextual text colors we just set their value to the brand contextual colors, and for the state contextual background colors, we are using the
bc. {color:#295646;}lighten function to make a slight change based on the contextual text colors.
Next, override the paddings value and border radius values for components:
{color:#295646;} bc. {color:#295646;}@padding-base-vertical: 8px; @padding-base-horizontal: 16px;
padding-large-vertical: 12px;
padding-large-horizontal: 24px;
padding-small-vertical: 6px;
padding-small-horizontal: 12px;
padding-xs-vertical: 2px;
padding-xs-horizontal: 6px;
border-radius-base: 0;
border-radius-large: 0;
@border-radius-small: 0;
@pager-border-radius: 0;
pre
Last, override some variables for navigation bar:
{color:#295646;} bc. {color:#295646;}@navbar-height: 60px;
navbar-default-color:
brand-primary;
navbar-default-bg: #fff;
navbar-default-link-color: #999;
navbar-default-link-hover-color:
brand-primary;
navbar-default-link-hover-bg: transparent;
navbar-default-link-active-color: brand-primary;
navbar-default-link-active-bg: transparent;
navbar-inverse-color:
gray-lighter;
navbar-inverse-bg:
brand-primary;
navbar-inverse-link-color:
gray-lighter;
navbar-inverse-link-hover-color: #fff;
navbar-inverse-link-hover-bg: transparent;
navbar-inverse-link-active-color:
navbar-inverse-link-hover-color;
@navbar-inverse-link-active-bg: transparent;
pre
That’s all for our my-variables.less file. We only overrode around 50 variables. Next let’s create my-theme.less, then import the Nunito font, Bootstrap’s Less file and our my-variables.less file:
{color:#295646;} bc. {color:#295646;}@import url('https://fonts.googleapis.com/css?family=Nunito:400,600,700'); @import "path/to/bootstrap-3.3.7/less/bootstrap.less"; @import "my-variables.less"; pre
Also in my-theme.less, let’s add some more customizations to the navigation bar: remove its border, add a little shadow and change the alert badge’s background color.
{color:#295646;} bc. {color:#295646;}.navbar { border: none; .box-shadow(0px 1px 1px 0px rgba(0, 0, 102, 0.1));&-default { .badge { background-color: #F23557; } } &-inverse { .badge { background-color: #f67f55; } } } pre
Notice here we utilized a mixin named
bc. {color:#295646;}.box-shadow, this mixin is defined in Bootstrap’s vendor-prefixes.less file at less/mixins folder. The line
bc. {color:#295646;}@import “path/to/bootstrap-3.3.7/less/bootstrap.less”; imports all of those mixins, so we can directly use
bc. {color:#295646;}.box-shadow here.
That’s it! We completed my-variables.less and my-theme.less, let’s compile my-theme.less to the CSS file:
{color:#295646;} bc. {color:#295646;}$ lessc my-theme.less my-theme.css pre
Then link it in our theme-styles.html:
{color:#295646;} bc. {color:#295646;}<link rel="stylesheet" href="my-theme.css"/> pre
Now let’s view the changes, here are some screenshots:
Under the default theme, the navigation bar and some buttons are:
Under our theme they are:
Recall we also changed the state contextual colors, which are used by components like alerts and panels. Under the default theme, the alerts are:
Under our theme they are:
The styles above look great, especially given we only have around 60 lines code in my-variables.less and 20 lines code in my-theme.less file. There are more changes on other components in this page, want to see all of them? Practice time!
Try to change the values of the 5 variables below in my-variables.less to your own colors:
{color:#295646;} bc. {color:#295646;}@brand-primary: #3B4A6B; @brand-success: #52D681; @brand-info: #22B2DA; @brand-warning: #FFC24A; @brand-danger: #F23557; pre
As a reference, here are 2 websites you can use to pick theme colors:
Once you replaced the above 5 colors with your own, save the file then use
bc. {color:#295646;}lessc to recompile my-theme.less:
bc. {color:#295646;}$ lessc my-theme.less my-theme.css. Now visit the web page at http://127.0.0.1:8080/chapter3/3.4/theme-styles.html, refresh the page to see the changes you made. Congratulations, now you have your first theme!
In the last section we only wrote around 80 lines code in total and made a light-color theme. In this section we are going to override more variables and make a dark-color theme. Let’s start with creating 2 files: my-variables.less and my-theme.less. We will define variables in my-variables.less, and then do more customization in my-theme.less.
Like what we did in last section, my favorite process to make a theme is first set value for some global variables, then do more customization based on how it looks. So for this dark-color theme:
Here is the first version of my-variables.less:
{color:#295646;} bc. {color:#295646;}// Global settings // ------------------------------ // ## font styles @font-family-sans-serif: "Roboto Condensed", Helvetica, Arial, sans-serif; @headings-font-weight: 700;
// ## background color
body-bg: #233142;
text-color: #e3e3e3;
// ## brand contextual colors
brand-primary: #ee6363;
brand-success: #62c462;
brand-info: #5bc0de;
brand-warning: #f0ad4e;
brand-danger: #C31207;
brand-secondary: #455D7A;
// ## Link and hr color
link-color:
brand-primary;
link-hover-color: darken(
link-color, 10%);
hr-border:
brand-secondary;
// ## state contextual colors
state-success-text: #fff;
state-success-bg: brand-success;
state-success-border: lighten(@brand-success, 5%);
state-info-text: #fff;
state-info-bg: brand-info;
state-info-border: lighten(@brand-info, 5%);
state-warning-text: #fff;
state-warning-bg: brand-warning;
state-warning-border: lighten(@brand-warning, 5%);
state-danger-text: #fff;
state-danger-bg: brand-danger;
state-danger-border: lighten(@brand-danger, 5%);
// ## border radius
border-radius-base: 2px;
border-radius-large: 4px;
border-radius-small: 3px;
pager-border-radius: 2px;
// ## paddings
padding-base-vertical: 8px;
padding-base-horizontal: 16px;
padding-large-vertical: 12px;
padding-large-horizontal: 24px;
padding-small-vertical: 6px;
padding-small-horizontal: 12px;
padding-xs-vertical: 2px;
padding-xs-horizontal: 6px;
pre
And in my-theme.less we have:
{color:#295646;} bc. {color:#295646;}// Import "Roboto Condensed" font @import url('https://fonts.googleapis.com/css?family=Roboto+Condensed:300,400,700');
// Import default bootstrap.less
@import “path/to/bootstrap-3.3.7/less/bootstrap.less”;
// Import our variables
@import “my-variables.less”;
pre
Let’s compile it:
{color:#295646;} bc. {color:#295646;}$ lessc my-theme.less my-theme.css pre
Link this compiled my-theme.css in our theme-style.html, then let’s view the page:
Typography:
Buttons:
Alert:
Looks good, doesn’t it? Notice now we only have around 60 lines of code, but clearly we need to do more work. Take a close look at the typography section in the screenshot above: the text contextual colors don’t work. For example, text with the
bc. {color:#295646;}.text-warning class still displays with a white color. Also some other components, like panels, look really bad:
But again, remember this is just our first step – defining some variables as global settings. Now let’s dig into each part to do more customizations.
If we check the screenshot above for typography part, there are several things we may want to change:
*
bc. {color:#295646;} and
bc. {color:#295646;} tag background color
If we check Bootstrap’s variables.less file, there are some variables we can find which are used for defining colors for the
bc. {color:#295646;},
bc. {color:#295646;} and
bc. {color:#295646;} tags, so let’s override those variables in our my-variables.less file:
{color:#295646;} bc. {color:#295646;}@code-color: @text-color; @code-bg: @brand-secondary; @pre-color: @text-color; @pre-bg: @brand-secondary; @pre-border-color: darken(@brand-secondary, 20%);
// ## blockquote
blockquote-border-color:
brand-secondary;
blockquote-small-color:
text-muted;
// ## contextual text
text-muted: lighten(
gray-base, 60%);
pre
For contextual text colors, you may notice we only defined the
bc. {color:#295646;}@text-muted variable, but where are other ones like
bc. {color:#295646;}@text-success,
bc. {color:#295646;}@text-warning ? If we check Bootstrap’s type.less file we can see those classes are originally defined as:
{color:#295646;} bc. {color:#295646;}.text-success { .text-emphasis-variant(@state-success-text); } .text-info { .text-emphasis-variant(@state-info-text); } pre
It uses a mixin called
bc. {color:#295646;}.text-emphasis-variant and pass the color as parameter to define the text color. In the my-variables.less global settings section, we defined
bc. {color:#295646;}@state-success-text,
bc. {color:#295646;}@state-info-text as a white color
bc. {color:#295646;}#fff, so that’s why our text with
bc. {color:#295646;}.text-success,
bc. {color:#295646;}.text-info classes display as a white color. Since those
bc. {color:#295646;}@state-success-text,
bc. {color:#295646;}@state-info-text are already defined in our global settings, we don’t want to change them, so let’s override these classes in our my-theme.less:
{color:#295646;} bc. {color:#295646;}// Typography // ------------------------------ h1, h2, h3, h4, h5, h6 { text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.3); }
.text-primary, .text-primary:hover {
.text-emphasis-variant(@brand-primary);
}
.text-success, .text-success:hover {
.text-emphasis-variant(@brand-success);
}
.text-danger, .text-danger:hover {
.text-emphasis-variant(@brand-danger);
}
.text-warning, .text-warning:hover {
.text-emphasis-variant(@brand-warning);
}
.text-info, .text-info:hover {
.text-emphasis-variant(@brand-info);
}
pre
Notice that we passed the
bc. {color:#295646;}@brand-success,
bc. {color:#295646;}@brand-info variables as the text color, and we also added a text shadow for our
bc. {color:#295646;}
{color:#295646;} bc. {color:#295646;}.bg-success { color: #fff; } .bg-info { color: #fff; } .bg-warning { color: #fff; } .bg-danger { color: #fff; } pre
OK, for this typography part, we made changes in both my-variables.less and my-theme.less, let’s recompile our theme:
{color:#295646;} bc. {color:#295646;}$ lessc my-theme.less my-theme.css pre
Refresh our theme-styles.html page, now our typography section looks like below:
Compared to the previous one, this one looks much better. That’s all we need for this typography section, now let’s move on to Navbar.
Let’s take a look at its current appearance:
It’s not bad, but since we are making a dark-color theme, I think we should make the color of
bc. {color:#295646;}.navbar-default class match the dark background color, so let’s change the background color of
bc. {color:#295646;}.navbar-default to our
bc. {color:#295646;}@brand-secondary, and change the background color of
bc. {color:#295646;}.navbar-inverse to some gray-like color. We can find which variable to override in the “Navbar” section of Bootstrap’s variables.less file, then override them. Below are variables we add to my-variables.less:
{color:#295646;} bc. {color:#295646;}// Navbar // ------------------------------ @navbar-height: 60px;
navbar-default-color:
text-color;
navbar-default-bg:
brand-secondary;
navbar-default-link-color:
text-color;
navbar-default-link-hover-color: #fff;
navbar-default-link-hover-bg: transparent;
navbar-default-link-active-color: #fff;
navbar-default-link-active-bg: transparent;
navbar-inverse-color:
body-bg;
navbar-inverse-bg: lighten(
text-color, 5%);
navbar-inverse-link-color:
brand-secondary;
navbar-inverse-link-hover-color: darken(
brand-secondary, 10%);
navbar-inverse-link-hover-bg: transparent;
navbar-inverse-link-active-color: navbar-inverse-link-hover-color;
navbar-inverse-link-active-bg: transparent;
navbar-inverse-brand-hover-color:
navbar-inverse-link-hover-color;
pre
And I’ll also change the input box and badge’s colors in both of these navbars, so let’s define some classes in my-theme.less file:
{color:#295646;} bc. {color:#295646;}// Navbar // ------------------------------ .navbar { border: none;&-default { .badge { background-color:
brand-primary;
}
.box-shadow(0px 1px 1px 0px rgba(0, 0, 102, 0.1));
input.form-control {
background-color: lighten(
brand-secondary, 5%);
}
}
&-inverse {
.badge {
background-color: brand-secondary;
}
.box-shadow(1px 0px 6px 0px rgba(0, 0, 0, 0.6));
input.form-control {
background-color: #eee;
border-color: #ccc;
&:focus {
color:
brand-secondary;
}
}
}
}
pre
We are all set for these Navbar components, now it looks like below:
I really like it! Notice if you want to make more changes, you can first check the “Navbar” section in Bootstrap’s variables.less to find variables to override, then check the current Navbar’s classes defined in Bootstrap’s navbar.less file, pick some and change their CSS properties. This is also the method we used to make customizations in the above Typography section.
We are going to apply the same method: first override variables related to buttons in my-variables.less, then make more customizations in my-theme.less if necessary. During this process, Bootstrap’s original variables.less and buttons.less files will be our reference.
Here are some variables we add in my-variables.less:
{color:#295646;} bc. {color:#295646;}// Buttons // ------------------------------ @btn-default-color: #fff; @btn-default-bg: @brand-secondary; @btn-default-border: darken(@btn-default-bg, 5%); pre
And in my-theme.less:
{color:#295646;} bc. {color:#295646;}// Buttons // ------------------------------ .btn { text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);&-link { text-shadow: none; box-shadow: none; } } pre
Notice I also added some text shadow and box shadow effects for buttons. Now let’s recompile my-theme.less to my-theme.css then view the changes, recall our button section’s previous appearance is:
After we made the change, now it looks like below:
The current look of the forms section:
It seems we need to change the input box’s background color, and apparently also add some changes to make
bc. {color:#295646;}.has-warning,
bc. {color:#295646;}.has-error, etc. classes work (notice currently the input boxes with those 2 classes look no different with the normal one). To make those changes, Bootstrap’s variables.less, forms.less and input-groups.less files are our reference. Here are the variables we override in my-variables.less:
{color:#295646;} bc. {color:#295646;}// Forms // ------------------------------ @input-bg: @brand-secondary; @input-color: @text-color; @input-border: darken(@brand-secondary, 5%); @input-border-focus: lighten(@brand-secondary, 10%); @input-bg-disabled: desaturate(@brand-secondary, 10%);
legend-color:
text-color;
legend-border-color:
brand-secondary;
pre
And in my-theme.less:
{color:#295646;} bc. {color:#295646;} // Forms // ------------------------------ .has-warning { .form-control-validation(@text-color: @brand-warning; @border-color: @brand-warning; @background-color: @input-bg); }
.has-error {
.form-control-validation(text-color:
brand-danger; border-color:
brand-danger; background-color:
input-bg);
}
.has-success {
.form-control-validation(text-color:
brand-success; border-color:
brand-success; background-color:
input-bg);
}
.input-group-addon:first-child {
background-color: brand-secondary;
color:
text-color;
}
pre
In the above code, for the
bc. {color:#295646;}.has-warning,
bc. {color:#295646;}.has-error and
bc. {color:#295646;}.has-success classes, we use Bootstrap’s mixin called
bc. {color:#295646;}.form-control-validation .
Now let’s compile my-theme.less and view the changes:
Compare it with the previous screenshot, the new one looks great and totally matches our dark-color theme!
The table section’s current look:
We only need to add some variables in my-variables.less file like below (no extra code in my-theme.less):
{color:#295646;} bc. {color:#295646;}// Table // ------------------------------ @table-bg: transparent; @table-bg-accent: @brand-secondary; @table-bg-hover: lighten(@brand-secondary, 3%); @table-bg-active: @table-bg-hover; @table-border-color: lighten(@brand-secondary, 3%); pre
Recompile our theme css file and view the changes:
If you want to make more changes, take a look at variables related to table in Bootstrap’s variables.less and tables.less file.
This section’s current appearance:
To make the change, the “Navs” section in Bootstrap’s variables.less and its navs.less file will be our references. Let’s make changes in both my-variables.less and my-theme.less. In my-variables.less:
{color:#295646;} bc. {color:#295646;}// Nav // ------------------------------ @nav-link-hover-bg: @brand-secondary;
nav-tabs-border-color:
brand-secondary;
nav-tabs-link-hover-border-color:
brand-secondary;
nav-tabs-active-link-hover-bg:
brand-secondary;
nav-tabs-active-link-hover-color: #fff;
nav-tabs-active-link-hover-border-color: @brand-secondary;
nav-tabs-justified-link-border-color:
brand-secondary;
nav-tabs-justified-active-link-border-color:
brand-secondary;
pre
In my-theme.less:
{color:#295646;} bc. {color:#295646;}// Nav // ------------------------------ .nav { .open > a { &, &:hover, &:focus { background-color: @nav-link-hover-bg; border-color: @nav-link-hover-bg; } } }
.nav-tabs {
> li > a {
color: text-color;
&:hover {
background-color:
brand-secondary;
}
}
}
.nav-pills {
> li > a {
color: text-color;
&:hover {
background-color:
brand-secondary;
}
}
}
pre
Recompile our theme CSS file, we now have:
For this component, the “Breadcrumbs” section in Bootstrap’s variables.less and its breadcrumbs.less file will be our references. Here I only want to make some changes for its color, so I just need to override some color variables in my-variable.less (no extra code in my-theme.less):
{color:#295646;} bc. {color:#295646;}// Breadcrumb // ------------------------------ @breadcrumb-bg: @brand-secondary; @breadcrumb-color: @text-color; @breadcrumb-active-color: @text-color; pre
Previous appearance:
Now:
Like the Breadcrumb component, I only want to change the color of pagination, so in my-variables.less I add:
{color:#295646;} bc. {color:#295646;}// Pagination // ------------------------------ @pagination-color: @text-color; @pagination-bg: @brand-secondary; @pagination-border: transparent;
pagination-hover-color: #fff;
pagination-hover-bg: darken(brand-secondary, 5%);
pagination-hover-border: transparent;
pagination-active-color: #fff;
pagination-active-bg: brand-primary;
pagination-active-border: transparent;
pagination-disabled-color: darken(
text-color, 20%);
pagination-disabled-bg: desaturate(
brand-secondary, 10%);
@pagination-disabled-border: transparent;
pre
Before:
After:
Again, if you want to make more changes, check the variables related to pagination in Bootstrap’s variables.less file and classes in pagination.less file.
Only some color variables need to be overwritten in my-variables.less:
{color:#295646;} bc. {color:#295646;}// List group // ------------------------------ @list-group-bg: @brand-secondary; @list-group-border: lighten(@list-group-bg, 3%); @list-group-link-heading-color: @text-color; @list-group-link-color: @text-color; @list-group-link-hover-color: @text-color; @list-group-hover-bg: @list-group-border; pre
Before:
After:
In the beginning we showed the current look of the Panels component:
Here are some variables I overrode in my-variables.less:
{color:#295646;} bc. {color:#295646;}// Panels // ------------------------------ // ## panel contextual color @panel-success-text: #fff; @panel-success-heading-bg: @brand-success;
panel-warning-text: #fff;
panel-warning-heading-bg: @brand-warning;
panel-danger-text: #fff;
panel-danger-heading-bg: @brand-danger;
panel-info-text: #fff;
panel-info-heading-bg: @brand-info;
panel-bg:
brand-secondary;
// ## Border color within panels
panel-inner-border: transparent;
panel-footer-bg: darken(@brand-secondary, 5%);
panel-default-border: transparent;
panel-default-heading-bg: darken(@brand-secondary, 5%);
panel-primary-border: transparent;
panel-success-border: transparent;
panel-info-border: transparent;
panel-warning-border: transparent;
@panel-danger-border: transparent;
pre
And code added in my-theme.less:
{color:#295646;} bc. {color:#295646;}// Panels // ------------------------------ .panel { border: none; &-default > .panel-heading { color: @text-color; } } pre
Recompile our theme file and view the change:
Like other components, if you want to make more customizations, take a look at the “Panels” section defined in Bootstrap’s variables.less and all classes defined in panels.less.
Current appearance:
I only need to change some color variables in my-variables.less:
{color:#295646;} bc. {color:#295646;}// Wells // ------------------------------ @well-bg: @brand-secondary; @well-border: lighten(@brand-secondary, 5%);
pre
Now it becomes:
Current appearance:
I added some variables in my-variables.less:
{color:#295646;} bc. {color:#295646;}// Modals // ------------------------------ @modal-content-bg: @brand-secondary; @modal-content-border-color: transparent; @modal-content-fallback-border-color: transparent;
modal-backdrop-bg: #000;
modal-backdrop-opacity: .5;
modal-header-border-color:
body-bg;
modal-footer-border-color:
modal-header-border-color;
pre
And classes in my-theme.less:
{color:#295646;} bc. {color:#295646;}// Modals // ------------------------------ .modal { padding: 0; &-header, &-footer { background-color: darken(@brand-secondary, 5%); border: none; } } pre
Its new appearance:
Beyond those components, I also added some other minor changes which are not listed above, but that’s all the major changes we made. Congratulations! To recap, to make a theme, the process we utilized is:
Can you follow the method we learned in this section to make a whole new theme? As references, you can:
In chapter 3 we created 2 themes based on the existing classes defined by Bootstrap, and they look great. However, to apply a theme to a real product, or sell a theme package to customers, sometimes using those pre-defined classes in Bootstrap is not enough. We also need to create some extra classes and use some plugins to power it up.
In this chapter, we are going to first make a new theme using the method we learned in chapter 3, and this will help us get more familiar with the process of making a theme. Then we will add extra classes to this theme. These classes are not defined by Bootstrap, but they are very handy and will boost up our theme. We will also introduce some Javascript plugins which will make components look more professional. Lastly, we will touch a little on how to organize files if we want to sell our themes on the marketplace. Let’s get started.
Let’s first make a simple theme and then later we will power it up with some extra CSS styles and Javascript plugins. To make this theme, we are going to use the same method we used in the previous chapter.
Here are variables we defined in my-variables.less:
{color:#295646;} bc. {color:#295646;}// font styles @font-family-sans-serif: Dosis, Helvetica, Arial, sans-serif; @headings-font-weight: 700; @text-color: #333;
// brand contextual colors
brand-primary: #ed745e;
brand-success: #2eb872;
brand-info: #497cb1;
brand-warning: #f89b20;
@brand-danger: #e03e36;
// state contextual colors
state-success-text: #fff;
state-success-bg: brand-success;
state-success-border: lighten(@state-success-bg, 5%);
state-info-text: #fff;
state-info-bg: brand-info;
state-info-border: lighten(@state-info-bg, 5%);
state-warning-text: #fff;
state-warning-bg: brand-warning;
state-warning-border: lighten(@state-warning-bg, 5%);
state-danger-text: #fff;
state-danger-bg: brand-danger;
state-danger-border: lighten(@state-danger-bg, 5%);
btn-default-color: #333;
btn-default-bg: #f9f9f9;
btn-default-border: darken(
btn-default-bg, 10%);
btn-primary-border:
brand-primary;
// Padding and border radius for components
padding-base-vertical: 8px;
padding-base-horizontal: 16px;
padding-large-vertical: 12px;
padding-large-horizontal: 24px;
padding-small-vertical: 6px;
padding-small-horizontal: 12px;
padding-xs-vertical: 2px;
padding-xs-horizontal: 6px;
border-radius-base: 0;
border-radius-large: 0;
@border-radius-small: 0;
@pager-border-radius: 0;
// Navbar
@navbar-height: 60px;
navbar-default-color:
brand-primary;
navbar-default-bg: #fff;
navbar-default-link-color: #555;
navbar-default-link-hover-color:
brand-primary;
navbar-default-link-hover-bg: transparent;
navbar-default-link-active-color: brand-primary;
navbar-default-link-active-bg: transparent;
navbar-inverse-color: #fff;
navbar-inverse-bg: darken(brand-primary, 5%);
navbar-inverse-link-color: #f5f5f5;
navbar-inverse-link-hover-color: #fff;
navbar-inverse-link-hover-bg: transparent;
navbar-inverse-link-active-color:
navbar-inverse-link-hover-color;
@navbar-inverse-link-active-bg: transparent;
// Pagination
pagination-disabled-color: #ddd;
pagination-disabled-bg: #fafafa;
pre
Then in my-theme.less we have:
{color:#295646;} bc. {color:#295646;}@import url('https://fonts.googleapis.com/css?family=Dosis:400,500,600,700'); @import "path/to/bootstrap-3.3.7/less/bootstrap.less"; @import "my-variables.less"; pre
So we imported the “Dosis” font and our own my-variables.less, after we compile it to my-theme.css, our theme-styles.html page looks like this:
It is not bad, but we still need to fix some styles and customize some components. For example, in the first screenshot, the font color of our contextual text classes, e.g.
{color:#295646;}.text-primary,
bc. {color:#295646;}.text-success are all white. We need to fix that, so we add following code to the [_my-theme.less_] file:
{color:#295646;} bc. {color:#295646;}// Typography .text-primary, .text-primary:hover { .text-emphasis-variant(@brand-primary); }
.text-success, .text-success:hover {
.text-emphasis-variant(@brand-success);
}
.text-danger, .text-danger:hover {
.text-emphasis-variant(@brand-danger);
}
.text-warning, .text-warning:hover {
.text-emphasis-variant(@brand-warning);
}
.text-info, .text-info:hover {
.text-emphasis-variant(@brand-info);
}
pre
Also I’ll add some customizations for other components like Navbar and Alerts, but I’ll skip listing the code here, basically I am just following the process we did in chapters 3.4 and 3.5. Also, since in this chapter we will mainly focus on the “additional classes and plugins”, we will just make a simple theme in this section, if you check the code in my-theme.less file under the repository folder chapter4/4.1, there are only around 100 lines of code.
Although it is a simple theme, the final version we have still looks neat:
Start a server to see all the components under this theme:
In this section we are going to add some power-ups. This includes some additional styles, components and animation effects. They are very helpful when we are building a real website using our theme. We will first create 2 files, my-mixins.less to save some extra mixins and my-extra-styles.less to save extra styles.
Since our my-extra-styles.less defines additional styles for the theme we make in section 4.1, let’s first import some files to set it up, at the beginning of file my-extra-styles.less let’s add the code below:
{color:#295646;} bc. {color:#295646;}@import "path/to/bootstrap-3.3.7/less/variables.less"; @import "path/to/bootstrap-3.3.7/less/mixins.less"; @import "path/to/chapter4/4.1/my-variables.less"; @import "my-mixins.less"; pre
We imported Bootstrap’s variables.less and our own my-variables.less files, also imported Bootstrap’s mixins.less and our own my-mixins.less (though currently it is empty) files. Later we will use those variables and mixins to define some extra styles and components.
Suppose we are building a website for a real product, it is common that we design the index page like this: a navigation bar at the top, followed by a beautiful banner image, and after it there is a “product features” section, etc.
If you browsed the theme-styles.html page in section 4.1, you can see the current navigation bar under the starter theme:
So if we use this theme to build the index page, we may write the HTML code like this:
{color:#295646;} bc. {color:#295646;}<nav class="navbar navbar-default navbar-fixed-top"> ... </nav> pre
The page looks like below:
The navigation bar is on top of the banner image, it does not look bad but there is a better and more popular way. When the user first opens this web page, make the background of the navigation bar be transparent, so it looks like it is a part of the banner image. As the user scrolls down the page a little, we change the navigation bar’s background back to the non-transparent color. This makes the navbar look like it “pops up” from the banner, and make it stand out of the page.
For example, when the user opens the page, at first the screen looks like:
After user scrolls down a little:
To achieve this, we need do the following things:
Let’s do it step by step, first is adding the
bc. {color:#295646;}.navbar-menu-top class:
{color:#295646;} bc. {color:#295646;}.navbar { &-menu-top { background: transparent; color: #fff; padding-top: 25px; .box-shadow(none);.navbar-brand { font-size: 1.6em; color: #f1f1f1; padding: 10px 15px; &:visited, &:hover { color: #f1f1f1; } } .navbar-nav > li { > a { font-size:1.1em; font-weight: 500; } > a:link, > a:visited { color: #f1f1f1; } > a:hover, > a:active { color:
brand-primary;
}
&.active > a {
color:
brand-primary;
}
}
}
}
pre
We add the
bc. {color:#295646;}.navbar-menu-top class, and also changed the
bc. {color:#295646;}.navbar-brand and
bc. {color:#295646;}.navbar-nav > li styles under it. After compiling this Less code to plain CSS, we apply it to our navbar:
{color:#295646;} bc. {color:#295646;}<nav class="navbar navbar-default navbar-fixed-top navbar-menu-top" id="navbar-top"> ... </nav> pre
We also assign an id named “navbar-top” to this navbar, which will be used in the second step: using Javascript to remove and add the
bc. {color:#295646;}.navbar-menu-top class when the user scrolls up and down the page:
{color:#295646;} bc. {color:#295646;}<script> $(window).scroll(function() { if ($(this).scrollTop() > 80) { $("#navbar-top").removeClass("navbar-menu-top"); } else { $("#navbar-top").addClass("navbar-menu-top"); } }); </script> pre
What this script does is, if the user scrolls the page down more than 80 pixels, we remove the navbar’s
bc. {color:#295646;}.navbar-menu-top class, otherwise, for example, if user the scrolls back up to the top, we add this class back to the navbar.
Lastly, as we remove and add this class to the navbar, the styles apply immediately. For example, when the navbar has
bc. {color:#295646;}.navbar-menu-top, it has a transparent background, when we use Javascript to remove this class, its background suddenly become non-transparent with a white color. We want to make this transition more smooth. Thanks to CSS3 transitions, we can achieve it by simply defining and applying some CSS:
{color:#295646;} bc. {color:#295646;}.transition-eio { .transition(all 0.3s ease-in-out); } pre
Here we used a mixin
bc. {color:#295646;}.transition which is imported from Bootstrap’s mixins.less, after compiled the above code, it becomes:
{color:#295646;} bc. {color:#295646;}.transition-eio { -webkit-transition: all 0.3s ease-in-out; -o-transition: all 0.3s ease-in-out; transition: all 0.3s ease-in-out; } pre
Then we can just add this class to our navbar:
{color:#295646;} bc. {color:#295646;}<nav class="navbar navbar-default navbar-fixed-top navbar-menu-top transition-eio" id="navbar-top"> ... </nav> pre
Now when the navbar uses or drops the
bc. {color:#295646;}.navbar-menu-top class, the browser will do a smooth transition for us. This
bc. {color:#295646;}.transition-eio we defined is quite handy. We can actually use it not only as a class but also as a mixin. We can apply it wherever we want to add a smooth transition for style changing. For example, we can use it as a mixin to the links in the previous navbar code written in Less :
{color:#295646;} bc. {color:#295646;}.navbar { a { .transition-eio; // use it as a mixin } ... } pre
With this mixin, when the user puts their mouse over a link, instead of immediately changing the link color, the browser will do a smooth color transition in 0.3 seconds.
To recap, what we did here includes 3 parts:
When we are making a web page, there is often a time when we want to add spaces between elements. For example, we put an icon and some text next to it, and we want a little spacing between this icon and the text. Instead of defining an inline
bc. {color:#295646;}margin-right style to that little icon in the CSS file, it will be handy if there are some predefined classes we can simply apply to this icon, so here we will define some spacing utility classes.
Take
bc. {color:#295646;}margin-right for example, we will add 5 classes for it:
bc. {color:#295646;}.mr-zero,
bc. {color:#295646;}.mr-xs,
bc. {color:#295646;}.mr-sm,
bc. {color:#295646;}.mr-md and
bc. {color:#295646;}.mr-lg. Specifically, they should be something like this:
{color:#295646;} bc. {color:#295646;}.mr-zero {margin-right: 0px} .mr-xs {margin-right: 5px} .mr-sm {margin-right: 12px} .mr-md {margin-right: 20px} .mr-lg {margin-right: 30px} pre
I set the pixels for xs to be 5px, sm to be 12px, but you can use different numbers. Then in the above example, we can apply it to the icon:
{color:#295646;} bc. {color:#295646;}<i class="fa fa-bell mr-xs"></i> <span>Some Text Here</span> pre
These are 5 classes for
bc. {color:#295646;}margin-right, and we will define similar classes for
bc. {color:#295646;}margin-left,
bc. {color:#295646;}margin-top,
bc. {color:#295646;}margin-right, also for
bc. {color:#295646;}padding-top,
bc. {color:#295646;}padding-bottom,
bc. {color:#295646;}padding-left and
bc. {color:#295646;}padding-right. Since each one has 5 classes and they are using the same pixels for
bc. {color:#295646;}*-xs,
bc. {color:#295646;}*-sm, etc., instead of manually writing every class, it will be helpful if we define a mixin first, then call it to generate those spacings. Specifically, let’s define a mixin called
bc. {color:#295646;}createSpacing in the my-mixins.less file:
{color:#295646;} bc. {color:#295646;}@spacing-size: zero 0px, xs 5px, sm 12px, md 20px, lg 30px;
.createSpacing(prefix,
property, iterator:1) when(
iterator <= length(spacing-size)) {
name: extract(extract(spacing-size,
iterator),1);
value: extract(extract(
spacing-size, iterator),2);
.
{prefix}[email protected]{name} {
{property}:
value;
}
.createSpacing(prefix,
property, (@iterator + 1));
}
pre
We use an iterator to loop through
bc. {color:#295646;}@spacing-size (if you are familiar with a programming language like Javascript, it is more like a recursive function call). To use it, we can write the code below in my-extra-styles.less:
{color:#295646;} bc. {color:#295646;}.createSpacing(mt, margin-top); pre
It is compiled to:
{color:#295646;} bc. {color:#295646;}.mt-zero {margin-top: 0px} .mt-xs {margin-top: 5px} .mt-sm {margin-top: 12px} .mt-md {margin-top: 20px} .mt-lg {margin-top: 30px} pre
We can do the same thing for other margins and paddings. Let’s add them in my-extra-styles.less:
{color:#295646;} bc. {color:#295646;}// mt-zero, mt-xs, mt-sm, mt-md, mt-lg .createSpacing(mt, margin-top); .createSpacing(mb, margin-bottom); .createSpacing(ml, margin-left); .createSpacing(mr, margin-right);
// pt-zero, pt-xs, pt-sm, pt-md, pt-lg
.createSpacing(pt, padding-top);
.createSpacing(pb, padding-bottom);
.createSpacing(pl, padding-left);
.createSpacing(pr, padding-right);
pre
After compilation, there will be 40 classes generated for spacing, like
bc. {color:#295646;}.mt-xs,
bc. {color:#295646;}.mr-sm,
bc. {color:#295646;}.pt-md,
bc. {color:#295646;}.pl-lg, etc.
Currently, we have contextual buttons like this:
In this section we will add another group of outline buttons, including the
bc. {color:#295646;}.btn-default-outline,
bc. {color:#295646;}.btn-primary-outline,
bc. {color:#295646;}.btn-success-outline,
bc. {color:#295646;}.btn-info-outline,
bc. {color:#295646;}.btn-warning-outline and
bc. {color:#295646;}.btn-danger-outline classes.
{color:#295646;} bc. {color:#295646;}.btn { .transition-eio;&-default-outline { .button-outline(#555); } &-primary-outline { .button-outline(
brand-primary);
}
&-success-outline {
.button-outline(
brand-success);
}
&-info-outline {
.button-outline(brand-info);
}
&-warning-outline {
.button-outline(
brand-warning);
}
&-danger-outline {
.button-outline(@brand-danger);
}
}
pre
Here we use a mixin
bc. {color:#295646;}.button-outline which is defined in my-mixins.less, we also use
bc. {color:#295646;}.transition-eio as a mixin, such that when the user hover over the button, the background color changes smoothly with an animation.
Here is our outline buttons’ appearance:
In this section, let’s add some contextual breadcrumb classes including
bc. {color:#295646;}.breadcrumb-primary,
bc. {color:#295646;}.breadcrumb-success,
bc. {color:#295646;}.breadcrumb-info,
bc. {color:#295646;}.breadcrumb-warning and
bc. {color:#295646;}.breadcrumb-danger.
{color:#295646;} bc. {color:#295646;}.breadcrumb-primary { .breadcrumb-contextual(@brand-primary); } .breadcrumb-success { .breadcrumb-contextual(@brand-success); } .breadcrumb-info { .breadcrumb-contextual(@brand-info); } .breadcrumb-warning { .breadcrumb-contextual(@brand-warning); } .breadcrumb-danger { .breadcrumb-contextual(@brand-danger); } pre
Each calls a mixin
bc. {color:#295646;}.breadcrumb-contexual which is defined in the my-mixins.less file. To use those classes, for example,
bc. {color:#295646;}.breadcrumb-primary, we can write code like below:
{color:#295646;} bc. {color:#295646;}<ol class="breadcrumb breadcrumb-primary"> <li><a href="#"><i class="fa fa-home"></i> Home</a></li> <li><a href="#">Users</a></li> <li class="active">Subscribers</li> </ol> pre
Our contextual breadcrumbs’ appearance:
Similar to breadcrumbs, let’s add contextual paginations:
{color:#295646;} bc. {color:#295646;}.pagination-primary { .pagination-contextual(@brand-primary); } .pagination-success { .pagination-contextual(@brand-success); } .pagination-info { .pagination-contextual(@brand-info); } .pagination-warning { .pagination-contextual(@brand-warning); } .pagination-danger { .pagination-contextual(@brand-danger); } pre
The
bc. {color:#295646;}.pagination-contextual mixin is also defined in my-mixins.less, you can check the source code there. We can use those pagination classes along with Bootstrap’s
bc. {color:#295646;}.pagination class like below:
{color:#295646;} bc. {color:#295646;}<ul class="pagination pagination-primary"> ... </ul> pre
Here are our contextual paginations appearance:
Under the current theme we can use contextual panel classes like
bc. {color:#295646;}.panel-primary,
bc. {color:#295646;}.panel-success,
bc. {color:#295646;}.panel-warning, etc. along with the
bc. {color:#295646;}.panel class:
{color:#295646;} bc. {color:#295646;}<div class="panel panel-primary"> <div class="panel-heading"> ... </div> <div class="panel-body"> ... </div> </div> pre
Here I am going to add another group of contextual panel classes which only change the top border color, I name them as
bc. {color:#295646;}.panel-default-top,
bc. {color:#295646;}.panel-primary-top,
bc. {color:#295646;}.panel-success-top,
bc. {color:#295646;}.panel-info-top,
bc. {color:#295646;}.panel-warning-top and
bc. {color:#295646;}.panel-danger-top. To use them in the above example, we can just replace the
bc. {color:#295646;}.panel-primary class with the
bc. {color:#295646;}.panel-primary-top class.
{color:#295646;} bc. {color:#295646;}<div class="panel panel-primary-top"> ... </div> pre
Their appearance:
The code is also simple:
{color:#295646;} bc. {color:#295646;}// Panel .panel-default-top { .panel-contextual-pos(#555, top); } .panel-primary-top { .panel-contextual-pos(@brand-primary, top); } .panel-success-top { .panel-contextual-pos(@brand-success, top); } .panel-info-top { .panel-contextual-pos(@brand-info, top); } .panel-warning-top { .panel-contextual-pos(@brand-warning, top); } .panel-danger-top { .panel-contextual-pos(@brand-danger, top); } pre
You may notice that here we are using a mixin named
bc. {color:#295646;}.panel-contextual-pos. This mixin is also defined in the my-mixins.less file, and we can use it as well to define panel classes which only change the bottom border color, like this:
{color:#295646;} bc. {color:#295646;}.panel-danger-bottom { .panel-contextual-pos(@brand-danger, bottom); } pre
Similarly, we can define the
bc. {color:#295646;}.panel-default-bottom,
bc. {color:#295646;}.panel-primary-bottom,
bc. {color:#295646;}.panel-success-bottom,
bc. {color:#295646;}.panel-info-bottom and
bc. {color:#295646;}.panel-warning-bottom classes. This should be easy and I’ll leave this as an exercise for you.
Like the outline buttons in 4.2.3, in this section we are going to define outline alerts:
{color:#295646;} bc. {color:#295646;}// Alert .alert-success-outline { .alert-variant(lighten(@brand-success, 53%), @brand-success, darken(@brand-success, 5%)); } .alert-info-outline { .alert-variant(lighten(@brand-info, 48%), @brand-info, darken(@brand-info, 5%)); } .alert-warning-outline { .alert-variant(lighten(@brand-warning, 43%), @brand-warning, darken(@brand-warning, 5%)); } .alert-danger-outline { .alert-variant(lighten(@brand-danger, 43%), @brand-danger, darken(@brand-danger, 5%)); } pre
The
bc. {color:#295646;}.alert-variant mixin above is imported from Bootstrap’s
bc. {color:#295646;}mixins.less, here we use it to define alerts with different background colors, border colors and text colors. We can compare the non-outline version and the outline version alerts:
Divs with the
bc. {color:#295646;}.alert and
bc. {color:#295646;}.alert-warning,
bc. {color:#295646;}.alert-success,
bc. {color:#295646;}.alert-danger,
bc. {color:#295646;}.alert-info classes:
Divs with the
bc. {color:#295646;}.alert and
bc. {color:#295646;}.alert-warning-outline,
bc. {color:#295646;}.alert-success-outline,
bc. {color:#295646;}.alert-danger-outline and
bc. {color:#295646;}.alert-info-outline classes:
The current list group item looks like this:
We are going to add 4 classes including
bc. {color:#295646;}.list-group-item-success,
bc. {color:#295646;}.list-group-item-info,
bc. {color:#295646;}.list-group-item-warning and
bc. {color:#295646;}.list-group-item-danger.
{color:#295646;} bc. {color:#295646;}.list-group-item-success { .list-group-item-contextual(@brand-success); } .list-group-item-info { .list-group-item-contextual(@brand-info); } .list-group-item-warning { .list-group-item-contextual(@brand-warning); } .list-group-item-danger { .list-group-item-contextual(@brand-danger); } pre
The mixin
bc. {color:#295646;}.list-group-item-contextual is defined in my-mixins.less:
{color:#295646;} bc. {color:#295646;}.list-group-item-contextual(@color) { background-color: @color; border: 1px solid @color; .badge { background-color: #fff; color: @color; } } pre
Then we can use it in HTML like this:
{color:#295646;} bc. {color:#295646;}<div class="list-group"> <a href="#" class="list-group-item list-group-item-success"> <span class="badge">2</span> Link item 1 </a> <a href="#" class="list-group-item"> Link item 2 </a> </div> pre
Their appearance:
Ribbon is an interesting and useful component, a common use case is adding it to a card to make the card stand out. In case you are not familiar with it, here is what we are going to make:
We need to add 3 classes:
#
bc. {color:#295646;}.ribbon-container: we will apply it to the card-like container, the key CSS property in this class is
bc. {color:#295646;}position:relative.
#
bc. {color:#295646;}.ribbon: a div which holds the actual ribbon, the key CSS properties in it are
bc. {color:#295646;}position:absolute; right:-1px; top:-1px; overflow:hidden. This div helps to locate the actual ribbon.
#
bc. {color:#295646;}.ribbon .text: class for the actual ribbon-look element. It includes the font color, background color properties, and most importantly, rotates the element 45 degrees. To achieve this, we can use CSS3’s property
bc. {color:#295646;}transform: rotate(45deg), or we can just call the
bc. {color:#295646;}.rotate(45deg) mixin which is imported from Bootstrap’s mixins.less.
{color:#295646;} bc. {color:#295646;}.ribbon-container { position: relative; }
.ribbon {
position: absolute;
right: -1px;
top: -1px;
z-index: 1;
overflow: hidden;
width: 75px;
height: 75px;
.text {
font-size: 14px;
font-weight: bold;
color: #FFF;
text-transform: uppercase;
text-align: center;
line-height: 20px;
.rotate(45deg);
width: 100px;
display: block;
background: #555;
position: absolute;
top: 15px;
right: -25px;
}
}
pre
Once these classes are defined, for contextual ribbons we only need to set the background color for the
bc. {color:#295646;}.text class, for example:
{color:#295646;} bc. {color:#295646;}.ribbon-primary { .text { background: @brand-primary; } } .ribbon-success { .text { background: @brand-success; } } pre
Then in HTML we can use this ribbon component like this:
{color:#295646;} bc. {color:#295646;}<div class="ribbon-container"> <h3>Some Title</h3> <p>Some Description</p> <div class="ribbon ribbon-primary"> <span class="text">HOT!</span> </div> </div> pre
Like ribbon, bookmark is another useful component to make card-like elements stand out. In this section we are going to make the contextual bookmark components:
We need to add following classes:
#
bc. {color:#295646;}.bookmark-container: Like the
bc. {color:#295646;}.ribbon-container class, we will apply this to the outer container, the key CSS property for it is
bc. {color:#295646;}position: relative.
#
bc. {color:#295646;}.bookmark: the actual bookmark. Here we will use a rectangle (e.g. a
bc. {color:#295646;}
#
bc. {color:#295646;}.bookmark::after: this is a pseudo element, and we will define some CSS properties for it to create a white triangle at the bottom of the rectangle to simulate the bookmark’s shape.
{color:#295646;} bc. {color:#295646;}.bookmark-container { position: relative; } .bookmark { display: inline-block; position: absolute; top: -1px; right: 12px; width: 28px; padding: 8px 0px 12px; color: #fff; background-color: #555; text-align: center;&::after { content: “”; position: absolute; bottom: 0; left: 0; width: 0; height: 0; border-bottom: 6px solid #fff; border-left: 14px solid transparent; border-right: 14px solid transparent; } } pre
Then for the contextual bookmarks we only need to set the background color, for example, for the
bc. {color:#295646;}.bookmark-primary and
bc. {color:#295646;}.bookmark-success classes we have:
{color:#295646;} bc. {color:#295646;}.bookmark-primary { background-color: @brand-primary; } .bookmark-success { background-color: @brand-success; } pre
To use this bookmark component, we can write HTML like this:
{color:#295646;} bc. {color:#295646;}<div class="bookmark-container"> <h3>Some Title</h3> <p> Some Description </p> <div class="bookmark bookmark-primary"> <i class="fa fa-star"></i> </div> </div> pre
In this section we are going to add some animation effects for an image when the user moves the mouse onto it. We will add 4 types of animations:
The first one is simple:
{color:#295646;} bc. {color:#295646;}.img-hover-fadeout:hover { .opacity(0.8); } pre
Here we use the
bc. {color:#295646;}.opacity mixin which is also imported from Bootstrap’s mixins.less file, then we can apply this class to an image like this:
{color:#295646;} bc. {color:#295646;}<img src="img-source-url" class="img img-responsive img-hover-fadeout transition-eio" /> pre
Notice we applied both the
bc. {color:#295646;}.img-hover-fadeout and
bc. {color:#295646;}.transition-eio classes to the image, the
bc. {color:#295646;}.img-hover-fadeout will change the image’s opacity, and the
bc. {color:#295646;}.transition-eio class will make the change more smooth with an animation.
For the second one, changing an image’s scale is easy too:
{color:#295646;} bc. {color:#295646;}.img-hover-scale:hover { .scale(1.2); } pre
The
bc. {color:#295646;}.scale mixin is imported from Bootstrap’s mixins.less file as well. But just using it with this class is not enough. We also need a container class such that when image zooms in, it will not exceed its container’s border:
{color:#295646;} bc. {color:#295646;}.img-hover-container { overflow:hidden; } pre
To use this class, we can write HTML like below:
{color:#295646;} bc. {color:#295646;}<div class="img-hover-container"> <img src="url" class="img img-responsive img-hover-scale transition-eio" /> </div> pre
The third one, scale and rotate:
{color:#295646;} bc. {color:#295646;}.img-hover-scale-rotate:hover { .transform(scale(1.2) rotate(8deg)); } pre
We set both the scale and rotate to the
bc. {color:#295646;}.transform mixin, this
bc. {color:#295646;}.transform mixin is defined in our own my-mixins.less file:
{color:#295646;} bc. {color:#295646;}.transform(@string){ -webkit-transform: @string; -moz-transform: @string; -ms-transform: @string; -o-transform: @string; transform: @string; } pre
Apply it to an image element:
{color:#295646;} bc. {color:#295646;}<div class="img-hover-container"> <img src="url" class="img img-responsive img-hover-scale-rotate transition-eio" /> </div> pre
Then when we move the mouse over this image, it will both zoom in and rotate 8 degrees.
The last one, the swing, costs more work since CSS3 doesn’t have a pre-made swing animation. To make it work, we need first define
bc. {color:#295646;}@keyframes named “swing”:
{color:#295646;} bc. {color:#295646;}@keyframes swing { 15% { .translate(5px; 0); } 30% { .translate(-5px; 0); } 50% { .translate(3px; 0); } 65% { .translate(-3px; 0); } 80% { .translate(2px; 0); } 100% { .translate(0; 0); } } pre
The
bc. {color:#295646;}.translate mixin is imported from Bootstrap’s mixins.less file, the parameters of it are the horizontal offset and vertical offset. If you are interested, the
bc. {color:#295646;}.translate mixin is defined as below:
{color:#295646;} bc. {color:#295646;}.translate(@x; @y) { -webkit-transform: translate(@x, @y); -ms-transform: translate(@x, @y); -o-transform: translate(@x, @y); transform: translate(@x, @y); } pre
Now for our swing class, we only need to use the keyframes we just defined:
{color:#295646;} bc. {color:#295646;}.img-hover-swing:hover { .animation(swing 1s ease-in-out); } pre
The
bc. {color:#295646;}.animation mixin is also imported from Bootstrap’s mixins.less file:
{color:#295646;} bc. {color:#295646;}.animation(@animation) { -webkit-animation: @animation; -o-animation: @animation; animation: @animation; } pre
Finally to use this
bc. {color:#295646;}.img-hover-swing class, we can write HTML like below, and when you move the mouse over on the image, it will swing left and right for 1 second, then stop:
{color:#295646;} bc. {color:#295646;}<div class="img-hover-container"> <img src="url" class="img img-responsive img-hover-swing" /> </div> pre
Since screenshot cannot show the animations we made, you can check all 4 in a web page at the end of this section:
(When you move the mouse over on the third image, you can see it both zooms in and rotates 8 degrees)
In the last part we are going to include some social media sign-in buttons, it is very common to see those buttons like “Sign in with Twitter”, “Sign in with Facebook” in a website’s Sign-in and Sign-up pages. So here we will add 8 commonly used third-party sign-in buttons including for Twitter, Facebook, Google, Github, Instagram, LinkedIn, Dropbox and OpenID.
Let’s first define a
bc. {color:#295646;}.btn-social class which contains the common CSS properties for all of those sign-in buttons:
{color:#295646;} bc. {color:#295646;}.btn-social { color: #fff; min-width: 200px; text-align: left;&:hover { color: #fff; } & > .fa { margin-right: 10px; padding-right: 10px; border-right: 1px solid rgba(0, 0, 0, 0.05); width: 30px; } } pre
We defined its width, text color and the icon styles (here we are using font-awesome icons, so the
bc. {color:#295646;}.fa indicates the icon’s class), then we can just define the background color for different social media.
{color:#295646;} bc. {color:#295646;}.btn-twitter { background: #55acee; &:hover { background: darken(#55acee, 10%); } }
.btn-facebook {
background: #3b5998;
&:hover {
background: darken(#3b5998, 10%);
}
}
pre
We can use them in HTML like below:
{color:#295646;} bc. {color:#295646;}<button class="btn btn-social btn-twitter"> <i class="fa fa-twitter"></i> Sign in with Twitter </button>
pre
Those 8 buttons’ appearances:
Start a server to see all the additional styles we defined:
In this section we will introduce some plugins that you can use along with Bootstrap, some of them are used for cool animations, some are for changing Bootstrap component’s appearance, etc.
Like we made the “swing” image in section 4.2, using CSS3 we can define some amazing animations. Here we are going to use a handy third-party CSS3 animation file, which is from http://www.justinaguilar.com/animations made by Justin Aguilar.
The CSS file (http://www.justinaguilar.com/animations/css/animations.css) defines several neat classes and we can simply apply them to an element to animate it. For example, suppose we have a
bc. {color:#295646;}div:
{color:#295646;} bc. {color:#295646;}<div class="section"> <h4>Some Title</h4> </div> pre
We can add a fadeIn class to it, then this div will show up with a fade-in animation:
{color:#295646;} bc. {color:#295646;}<div class="section fadeIn"> ... </div> pre
Even better, with Javascript we can dynamically add those animations. For example, for some elements not in the first screen, we can first set their visibility to be hidden:
{color:#295646;} bc. {color:#295646;}<style> .slide-item {visibility: hidden} </style> ... <div class="section slide-item"> ... </div> pre
Then as we scroll down the page a bit, we can use Javascript to add an animation class to this element, say we add a “slideUp” class to it:
{color:#295646;} bc. {color:#295646;}$(".slide-item").each(function(){ var itemTop = $(this).offset().top; var topOffset = $(window).scrollTop(); if (itemTop < topOffset + 550) { $(this).addClass("slideUp"); } }); pre
This element (the second row in the above picture) will appear from bottom with a slide-up animation.
Above is an example for applying the “slideUp” class, but we can simply change it to other animation classes like “slideLeft”, “fadeIn”, and “expandUp” which are defined in that animations.css file.
It is common to use a checkbox as a switch, for example:
And on the mobile apps, people are getting used to the switch’s interface like this:
While Bootstrap3 doesn’t come with a nice-looking “switch” component like above, we can use a third-party library called Bootstrap Switch (http://bootstrapswitch.com/), which can help us easily change a checkbox to a switch-like component.
Say in HTML we have a checkbox:
{color:#295646;} bc. {color:#295646;}<input type="checkbox" name="bs-switch" checked /> pre
To use the bootstrap-switch library, we need first import its CSS and JavaScript file:
{color:#295646;} bc. {color:#295646;}<link rel="stylesheet" href="switch/css/bootstrap-switch.min.css"/> ... <script src="switch/js/bootstrap-switch.min.js"></script> pre
Then write Javascript that simply calls the
bc. {color:#295646;}.bootstrapSwitch function:
{color:#295646;} bc. {color:#295646;}$("[name='bs-switch']").bootstrapSwitch(); pre
There is an option parameter for this function, where we can change this switch’s size, on & off label texts, on & off colors, etc:
{color:#295646;} bc. {color:#295646;}$("[name='bs-switch']").bootstrapSwitch({ size: "small", onText: "Yes", offText: "No", }); pre
Below are some examples I made. You can check the source code in file chapter4/4.3/plugins.html to see how it works.
A color picker would be a useful component if your website provides some color customization features, for example, you can change the theme color of your Twitter account profile page:
In the above text input box, the user could either choose pre-made colors or type some RGB hex color code. Suppose your website has a the similar function, you may consider adding a color picker to let the user pick a color from a palette, which would be more convenient than manually typing a hex code.
So here is the plugin we are going to utilize, called Bootstrap Colorpicker (https://itsjavi.com/bootstrap-colorpicker/). Like the “switch” plugin, first we need to import its CSS and Javascript files:
{color:#295646;} bc. {color:#295646;}<link rel="stylesheet" href="colorpicker/css/bootstrap-colorpicker.min.css"/> ... <script src="colorpicker/js/bootstrap-colorpicker.min.js"></script> pre
Next let’s code the input box in HTML then use Javascript to turn it into a color picker:
{color:#295646;} bc. {color:#295646;}<div class="input-group colorpicker-component cp"> <input type="text" class="form-control" value="#00b2ff"/> <span class="input-group-addon"><i></i></span> </div> ... <script> $(".cp").colorpicker(); </script> pre
The
bc. {color:#295646;}.colorpicker function also takes an option parameter, from where we can customize its alignment, format, etc. Here are some working examples, and you can check the source code for them in chapter4/4.3/plugins.html .
In this section we will cover 2 commonly used comports, date and time picker. They are from 2 different sources:
The usage is similar to the color picker. Take the date picker for example, first we need to include its CSS and Javascript files:
{color:#295646;} bc. {color:#295646;}<link rel="stylesheet" href="datepicker/css/bootstrap-datepicker3.min.css"/> ... <script src="datepicker/js/bootstrap-datepicker.min.js"></script> ... pre
Then call the
bc. {color:#295646;}.datapicker function on an element:
{color:#295646;} bc. {color:#295646;}<div class="input-group date dp"> <input type="text" class="form-control" value="04/16/2017"> <span class="input-group-addon"><i class="fa fa-calendar"></i></span> </div> ... <script> $(".dp").datepicker(); </script> pre
And below is a working example for the time picker. I’ll skip the its code here, but you can check the code in chapter4/4.3/plugins.html.
Lightbox is almost an indispensable component when you are trying to display a bunch of pictures, while Bootstrap provides the “modal” component which we can use along with some Javascript to make a lightbox. There is a plugin called Lightbox for Bootstrap (http://ashleydw.github.io/lightbox/) we can use directly.
First include its CSS and Javascript:
{color:#295646;} bc. {color:#295646;}<link rel="stylesheet" href="lightbox/css/ekko-lightbox.min.css"/> ... <script src="lightbox/js/ekko-lightbox.min.js"></script> ... pre
Say in HTML we have a bunch of images. If we want to show them in a lightbox, make sure give them the same value for the
bc. {color:#295646;}data-gallery attribute:
{color:#295646;} bc. {color:#295646;}<div class="col-xs-12 col-sm-3 text-center mb-lg"> <h4 class="section-subtitle mb-md">Picture #1</h4> <a href="image1-full-size-url" data-toggle="lightbox" data-gallery="gallery-1"> <img src="image1-thumbnail-url" class="img img-responsive"> </a> </div> <div class="col-xs-12 col-sm-3 text-center mb-lg"> <h4 class="section-subtitle mb-md">Picture #2</h4> <a href="image2-full-size-url" data-toggle="lightbox" data-gallery="gallery-1"> <img src="image2-thumbnail-url" class="img img-responsive"> </a> </div> pre
Then add Javascript such that when the user clicks any of those images, the lightbox will popup:
{color:#295646;} bc. {color:#295646;}$("[data-toggle='lightbox']").click(function (evt) { evt.preventDefault(); $(this).ekkoLightbox(); }); pre
Here are screenshots of a working example. We have 4 images with the same value of
bc. {color:#295646;}data-gallery attribute:
When clicking any of the images, a lightbox will popup, and we can use the left/right arrow keys to navigate back and forth.
These are all 5 plugins we introduced in this section, for more, please check “plugins” part in Appendix B.
Start a server to see all the plugins we added:
You have seen how we applied the CSS animations to HTML elements. Those CSS animations are included from the file http://www.justinaguilar.com/animations. Can you write some other animations and use it to some elements?
In this last section of this chapter, we are going to cover how to organize your theme files if you want to sell it in the marketplace.
The general rule here is that you may need to organize files clearly and include all the source files you made in case your customer wants to do more customizations. Here is a structure I am using:
To include what pages as templates, it depends on what kind of website you make, but in general you may want to include the sample pages below:
If you want your theme to be used for some e-commerce website, you may also include:
If your theme is mainly used for an admin site, you may want to include:
There are some other ways to organize those files. As long as you keep those files in a clear structure, you will save your customers lots of time to use or do further customizations to your theme.
Moreover, if you are looking for popular marketplaces to sell your themes, I put some in the “Marketplace” section of Appendix B.
At the time of writing this book, Bootstrap 4 is still in the alpha-test phase. Since it might have been officially released by the time you are reading this book, we will walk through some code of Bootstrap 4 to get you prepared for making themes for Bootstrap 4. Here we use its tag version v4.0.0-alpha.6, which is the latest version at this time. For the name convenience, in the following sections, by “Bootstrap 4” we mean “Bootstrap 4 at version v4.0.0-alpha.6”.
This version has lots of changes compared to version 3. Bootstrap 4 dropped lots of classes from Bootstrap 3, and introduced some new ones. For example, the
bc. {color:#295646;}.panel class is dropped, we can now use the new class named
bc. {color:#295646;}.card to implement the same look like
bc. {color:#295646;}.panel. Glyphicons are also dropped, using third-party icons like FontAwesome are recommended. Bootstrap 4 also uses flexbox for layout by default. We will cover those main changes in section 5.1.
For the CSS pre-processor part, Bootstrap 4 now use Sass instead of Less. Like we mentioned in chapter 2, Less and Sass are the most 2 popular CSS pre-processors, and Bootstrap 4 now opts to using Sass. Don’t worry if you are not familiar with Sass, it actually has very similar syntax to Less. If you have read chapter 2 about Less, you should be able to learn Sass very quickly. We will also cover an introduction on it in section 5.2.
Like we did for Bootstrap 3, knowing the source code structure of Bootstrap 4 will help us make customized themes, so in section 5.3 we will dive into Bootstrap 4’s source code. In the final section we will cover some customization tips for Bootstrap 4.
Bootstrap 4 has lots of changes compared to version 3, it deprecated some CSS classes and added some new ones, so we need to modify our code in theme-styles.html first to get us prepared for making themes.
If you are already familiar with Bootstrap 4, you can jump to the end of this section: in the practice part, you can set up a local server to preview our modified theme-styles.html with Bootstrap 4. Otherwise, if you are a Bootstrap 3 user, going through all of the content in this section will help you learn the changes in Bootstrap 4, and furthermore, learn how to use Bootstrap 4.
The first part in the typography section are the headings elements,
bc. {color:#295646;}h1 to
bc. {color:#295646;}h6. Bootstrap 4 removed their
bc. {color:#295646;}margin-top value and add
bc. {color:#295646;}margin-bottom: 0.5rem to all of them, so if we want to display them the same as Bootstrap 3, we need to add some
bc. {color:#295646;}margin-top values to them. Fortunately, we don’t need to define the same CSS classes ourselves, Bootstrap 4 comes with a bunch of utilities classes for spacing (like what we did in chapter 4.2), for example, for
bc. {color:#295646;}margin-top, it provides 6 classes:
bc. {color:#295646;}.mt-0,
bc. {color:#295646;}.mt-1,
bc. {color:#295646;}.mt-2,
bc. {color:#295646;}.mt-3,
bc. {color:#295646;}.mt-4 and
bc. {color:#295646;}.mt-5.
bc. {color:#295646;}.mt-0 will set
bc. {color:#295646;}margin-top value to be 0,
bc. {color:#295646;}.mt-5 will set it to
bc. {color:#295646;}3rem.
For example, we could add the
bc. {color:#295646;}.mt-4 class to
bc. {color:#295646;}h1,
bc. {color:#295646;}h2 and
bc. {color:#295646;}h3,
bc. {color:#295646;}.mt-2 to
bc. {color:#295646;}h4,
bc. {color:#295646;}h5 and
bc. {color:#295646;}h6 :
{color:#295646;} bc. {color:#295646;}<h1 class="mt-4">Heading 1, h1</h1> <h2 class="mt-4">Heading 2, h2</h2> <h3 class="mt-4">Heading 3, h3</h3> <h4 class="mt-2">Heading 4, h4</h4> <h5 class="mt-2">Heading 5, h5</h5> <h6 class="mt-2">Heading 6, h6</h6> pre
The second part includes the
bc. {color:#295646;}
,
bc. {color:#295646;},
bc. {color:#295646;},
bc. {color:#295646;}, and
bc. {color:#295646;} tags. They are basically the same as Bootstrap 3. The only change is the
bc. {color:#295646;} tag, which doesn’t have a border or background color anymore.
The third part is the
bc. {color:#295646;}blockquote tag. We need to explicitly add the
bc. {color:#295646;}.blockquote class to it. Also, for footnotes, we need to add a
bc. {color:#295646;}.blockquote-footer class. Recall in Bootstrap 3 we have:
{color:#295646;} bc. {color:#295646;}<blockquote> <p> Blockquote: quoted text here </p> <small>some celebrity</small> </blockquote> pre
Now we need to change it to:
{color:#295646;} bc. {color:#295646;}<blockquote class="blockquote"> <p> Blockquote: quoted text here </p> <footer class="blockquote-footer">some celebrity</footer> </blockquote> pre
The last part is contextual text including the
bc. {color:#295646;}.text-muted,
bc. {color:#295646;}.text-primary,
bc. {color:#295646;}.text-danger, etc. We don’t need to change them, but contextual background (like
bc. {color:#295646;}.bg-primary,
bc. {color:#295646;}.bg-danger, etc.) don’t set the text color by default anymore, so with the background color, the text doesn’t look very well:
But we may add a
bc. {color:#295646;}.text-white class to change the text color to white.
{color:#295646;} bc. {color:#295646;}<p class="bg-primary text-white">Text inside p with bg-primary class</p> <p class="bg-warning text-white">Text inside p with bg-warning class</p> <p class="bg-danger text-white">Text inside p with bg-danger class</p> ... pre
There is no
bc. {color:#295646;}.navbar-default class in Bootstrap 4. Now we need to use
bc. {color:#295646;}.bg-* utility classes to set the navigation bars color. This actually gives us more flexibility since Bootstrap 4 provided 7
bc. {color:#295646;}.bg-* classes including
bc. {color:#295646;}.bg-primary,
bc. {color:#295646;}.bg-success,
bc. {color:#295646;}.bg-info,
bc. {color:#295646;}.bg-warning,
bc. {color:#295646;}.bg-danger,
bc. {color:#295646;}.bg-inverse and
bc. {color:#295646;}.bg-faded. We can use those along with the
bc. {color:#295646;}.navbar-light and
bc. {color:#295646;}.navbar-inverse classes: if the background is a light color (like
bc. {color:#295646;}.bg-faded), use
bc. {color:#295646;}.navbar-light, so the text color in the navigation bar will turn dark; if the background is a dark color (like
bc. {color:#295646;}.bg-danger), use
bc. {color:#295646;}.navbar-inverse, so the text color in the navigation bar will turn light. So now for the navigation bar we have it like this:
{color:#295646;} bc. {color:#295646;}<nav class="navbar navbar-toggleable-md navbar-light bg-faded"> ... </nav> pre
For the link items in navigation bar, we need to add
bc. {color:#295646;}.nav-item to
bc. {color:#295646;}
{color:#295646;} bc. {color:#295646;}<ul class="navbar-nav mr-auto"> <li class="nav-item active"> <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a> </li> ... </ul> pre
We also need to change the alert badge’s classes. Bootstrap provided 6 badge background colors:
bc. {color:#295646;}.badge-default,
bc. {color:#295646;}.badge-primary,
bc. {color:#295646;}.badge-success,
bc. {color:#295646;}.badge-info,
bc. {color:#295646;}.badge-warning, and
bc. {color:#295646;}.badge-danger. It also has a
bc. {color:#295646;}.badge-pill class if we want to make the badge border more rounded. Here is our code for the badge:
{color:#295646;} bc. {color:#295646;}<li class="nav-item"> <a href="#" class="nav-link">Alerts <span class="badge badge-default badge-pill">3</span> </a> </li> pre
The great part is now we can combine those
bc. {color:#295646;}.bg-*,
bc. {color:#295646;}.navbar-light/inverse, and
bc. {color:#295646;}.badge-* classes to generate several different navigation bars, for example:
The first one we use
bc. {color:#295646;}.navbar-light and
bc. {color:#295646;}.bg-faded for
bc. {color:#295646;}
The second one we use
bc. {color:#295646;}.navbar-inverse and
bc. {color:#295646;}.bg-inverse for
bc. {color:#295646;}
The third one we use
bc. {color:#295646;}.navbar-danger and
bc. {color:#295646;}.bg-inverse for
bc. {color:#295646;}
There are several changes for buttons:
#
bc. {color:#295646;}.btn-default is renamed to
bc. {color:#295646;}.btn-secondary.
#
bc. {color:#295646;}.btn-xs is removed.
{color:#295646;} bc. {color:#295646;}<p> <h3>Outline buttons</h3> <a href="#" class="btn btn-outline-secondary">Secondary</a> <a href="#" class="btn btn-outline-primary">Primary</a> <a href="#" class="btn btn-outline-success">Success</a> <a href="#" class="btn btn-outline-info">Info</a> <a href="#" class="btn btn-outline-warning">Warning</a> <a href="#" class="btn btn-outline-danger">Danger</a> </p>
Changes for forms:
Bootstrap 4 also added a set of classes to show customized form controls. Using those classes can keep your form control, e.g. select, checkbox, radio, consistent across different browsers. Those custom classes include
bc. {color:#295646;}.custom-control,
bc. {color:#295646;}.custom-checkbox,
bc. {color:#295646;}.custom-radio,
bc. {color:#295646;}.custom-select,
bc. {color:#295646;}.custom-control-input,
bc. {color:#295646;}.custom-control-indicator, etc.
For example, to show a checkbox with
bc. {color:#295646;}.custom-* classes, we can do:
{color:#295646;} bc. {color:#295646;}<label class="custom-control custom-checkbox"> <input type="checkbox" class="custom-control-input"> <span class="custom-control-indicator"></span> <span class="custom-control-description">Custom checkbox 1</span> </label> pre
We can compare the differences between the native style and customized style of those form controls.
Open with Google Chrome in macOS:
Open with Firefox in macOS:
We can see that with different browsers, the native style of checkbox looks different (in Google Chrome, it is slightly bigger), while the customized style stays consistent.
There are only 2 changes we need to notice:
Changes for images:
*
bc. {color:#295646;}.img-responsive is renamed to
bc. {color:#295646;}.img-fluid.
For tabs and pills, we need to add
bc. {color:#295646;}.nav-item to each
bc. {color:#295646;}
{color:#295646;} bc. {color:#295646;}<ul class="nav nav-tabs"> <li class="nav-item"> <a class="nav-link" href="#">Home</a> </li> </ul> <ul class="nav nav-pills"> <li class="nav-item"><a class="nav-link active" href="#">Home</a></li> <li class="nav-item"><a class="nav-link" href="#">Page1</a></li> </ul> pre
The only change is we need to add a
bc. {color:#295646;}.breadcrumb-item class to each list item like this:
{color:#295646;} bc. {color:#295646;}<ul class="breadcrumb"> <li class="breadcrumb-item"><a href="#">Home</a></li> <li class="breadcrumb-item active">Library</li> </ul> pre
We need to add
bc. {color:#295646;}.page-item to each
bc. {color:#295646;}
{color:#295646;} bc. {color:#295646;}<ul class="pagination"> <li class="page-item active"><a class="page-link" href="#">1</a></li> <li class="page-item"><a class="page-link" href="#">2</a></li> </ul> pre
The pager component is dropped, since it can be easily made by using outline buttons, so here we will simply remove this “pagers” section.
There are no changes for the “Alerts” component.
The
bc. {color:#295646;}.label,
bc. {color:#295646;}.label-success,
bc. {color:#295646;}.label-warning, etc. classes are dropped, now we can use
bc. {color:#295646;}.badge-* classes, for example,
bc. {color:#295646;}.badge,
bc. {color:#295646;}.badge-success.
For badges, we need to use an extra
bc. {color:#295646;}.badge-pill class to make badges have a more rounded border. We can use it along with the
bc. {color:#295646;}.badge class to simulate the same look in Bootstrap 3.
{color:#295646;} bc. {color:#295646;}<span class="badge badge-default">label default</span> <span class="badge badge-success">label success</span> <span>Alerts <span class="badge badge-pill badge-default">4</span></span> pre
To show badges on the right of list group item, we need to add the
bc. {color:#295646;}.justify-content-between class:
{color:#295646;} bc. {color:#295646;}<li class="list-group-item justify-content-between"> List group item 1 <span class="badge badge-pill badge-default">1</span> </li> pre
Use the
bc. {color:#295646;}.list-group-item-action with
bc. {color:#295646;}.list-group-item to make an item actionable with hover and active states.
{color:#295646;} bc. {color:#295646;}<div class="list-group"> <a href="#" class="list-group-item list-group-item-action">Link item 3</a> <a href="#" class="list-group-item list-group-item-action">Link item 4</a> </div> pre
The new code template for a media object is:
{color:#295646;} bc. {color:#295646;}<div class="media"> <a href="#"> <img class="d-flex mr-3" src="http://lorempixel.com/50/50/animals/"/> </a> <div class="media-body"> <h5>Media Heading</h5> Media content </div> </div> pre
4 progress bar classes are dropped, including
bc. {color:#295646;}.progress-bar-success,
bc. {color:#295646;}.progress-bar-info,
bc. {color:#295646;}.progress-bar-warning and
bc. {color:#295646;}.progress-bar-danger, since we can use
bc. {color:#295646;}.bg-success,
bc. {color:#295646;}.bg-info, etc. to implement it. For example:
{color:#295646;} bc. {color:#295646;}<div class="progress"> <div class="progress-bar bg-success" style="width: 40%"></div> </div> pre
The
bc. {color:#295646;}.progress-striped is also dropped. Now we use the
bc. {color:#295646;}.progress-bar-striped and the
bc. {color:#295646;}.progress-bar classes to implement striped progress bars:
{color:#295646;} bc. {color:#295646;}<div class="progress"> <div class="progress-bar progress-bar-striped bg-info" style="width: 20%"></div> </div> pre
Panels are dropped in Bootstrap 4, but we can easily make it by using a newly introduced
bc. {color:#295646;}.card class.
For basic panels:
{color:#295646;} bc. {color:#295646;}<div class="card"> <div class="card-header"> Panel heading </div> <div class="card-block"> Panel content </div> <div class="card-footer"> Panel footer </div> </div> pre
For contextual panels, we can use the
bc. {color:#295646;}.card-outline-* class to change the border color, use
bc. {color:#295646;}.bg-* to fill the card header and use the
bc. {color:#295646;}.text-white to change header’s text color to white. For example:
{color:#295646;} bc. {color:#295646;}<div class="card card-outline-success"> <div class="card-header bg-success text-white"> Panel success </div> <div class="card-block"> Panel content </div> </div> pre
We use the
bc. {color:#295646;}.card-outline-success and
bc. {color:#295646;}.bg-success in the above example, you can change it to other contextual colors like
bc. {color:#295646;}.card-outline-danger and
bc. {color:#295646;}.bg-danger.
For panels with list groups, we need to add a class named
bc. {color:#295646;}.list-group-flush to the
bc. {color:#295646;}
{color:#295646;} bc. {color:#295646;}<div class="card"> <div class="card-header">Panel heading</div> <div class="card-block">Panel content </div> <ul class="list-group list-group-flush"> <li class="list-group-item">item 1</li> </ul> </div> pre
The wells component is also dropped, again we can use the
bc. {color:#295646;}.card class and padding utility classes
bc. {color:#295646;}.p-0 to
bc. {color:#295646;}.p-5 to implement it. In the example below we used
bc. {color:#295646;}.bg-faded to fill a gray background color for the well, but you can use other background colors like
bc. {color:#295646;}.bg-success,
bc. {color:#295646;}.bg-info, etc. to show a different color.
{color:#295646;} bc. {color:#295646;}<div class="col-xs-12 col-sm-4"> <div class="card p-3 bg-faded"> Text in a default well. </div> </div> <div class="col-xs-12 col-sm-4"> <div class="card p-2 bg-faded"> Text in a small well. </div> </div> <div class="col-xs-12 col-sm-4"> <div class="card p-4 bg-faded"> Text in a large well. </div> </div> pre
For modals, to let the close button display on the top-right corner, we need to put it after the
bc. {color:#295646;}.modal-title element (in Bootstrap 3 we can put it before
bc. {color:#295646;}.modal-title, it will still show on the top-right corner). For example:
{color:#295646;} bc. {color:#295646;}<div class="modal-header"> <h4 class="modal-title">Modal title</h4> <button type="button" class="close" data-dismiss="modal" aria-hidden="true"> × </button> </div> pre
There are no changes for this part.
Tooltips now rely on a third party library called Tether (website: http://tether.io/, github: https://github.com/HubSpot/tether). To make the tooltips component work, we must include its Javascript file before bootstrap.js.
{color:#295646;} bc. {color:#295646;}... <script src="https://rawgit.com/HubSpot/tether/master/dist/js/tether.min.js"> </script> <script src="/path/to/bootstrap-4.0.0-alpha.6/dist/js/bootstrap.min.js"> </script> ... pre
No changes for jumbotron, but to control the font size for the headline in jumbotron, like
bc. {color:#295646;}
{color:#295646;} bc. {color:#295646;}<div class="jumbotron"> <h1 class="display-3" id="jumboheader">Hello, world!</h1> <p class="lead">This is a simple hero unit, a simple jumbotron-style component.</p> <p class="lead"><a class="btn btn-primary btn-lg" href="#">Learn more</a></p> </div> pre
There are 2 changes for the carousel component:
The above changes are all we need to make for the theme-styles.html page, now it is time for you to view all of them:
Like Less we introduced in Chapter 2, Sass is also a superset of CSS and it has very similar syntax like Less. Since now you should be familiar with Less, here we will do a quick overview.
In order to use Sass, we need to install the
bc. {color:#295646;}sass command (like the
bc. {color:#295646;}lessc command we used before), check the installation instructions at: http://sass-lang.com/install.
Once it is installed, we can use it in our command/terminal window:
{color:#295646;} bc. {color:#295646;}$ sass test.scss test.css pre
It basically used the same way as we used Less before:
bc. {color:#295646;}$ lessc test.less test.css. Notice in the above line, though the compiling command is
bc. {color:#295646;}sass, the file is named with a suffix .scss, not .sass.
Less uses the
bc. {color:#295646;}@ symbol to define a variable, Sass uses the
bc. {color:#295646;}$ symbol, for example:
{color:#295646;} bc. {color:#295646;}$color-warning: #ff6600; .panel-warning { color: $color-warning; } pre
is compiled to:
{color:#295646;} bc. {color:#295646;}.panel-warning { color: #ff6600; } pre
Another difference is, _Less _ uses
bc. {color:#295646;}@{variable-name} for string interpolation , while Sass uses
bc. {color:#295646;}#{$variable-name}:
{color:#295646;} bc. {color:#295646;}$alertname: alert; .#{$alertname}-info { background-color: #339900; } pre
is compiled to:
{color:#295646;} bc. {color:#295646;}.alert-info { background-color: #339900; } pre
In addition, Sass provides a
bc. {color:#295646;}!default keyword that we can assign to variables if they haven’t been assigned yet. For example:
{color:#295646;} bc. {color:#295646;}$color: #ff6600; $color: #339900 !default; $font-base-size: 14px !default;
p {
color: $color;
font-size: $font-base-size;
}
pre
We can interpret the
bc. {color:#295646;}!default keyword to “if this variable doesn’t have a value yet, use this one; otherwise, ignore this one”. In the above example, we use
bc. {color:#295646;}!default in the second line for the variable
bc. {color:#295646;}$color, but
bc. {color:#295646;}$color has been defined in the first line, so the second value
bc. {color:#295646;}#339900 will be ignored. For the third line, the
bc. {color:#295646;}$font-base-size case, since this variable hasn’t been defined before,
bc. {color:#295646;}14px will be used. Thus, the above code will be compiled to this:
{color:#295646;} bc. {color:#295646;}p { color: #ff6600; font-size: 14px; } pre
About variables, there is another major difference between Less and Sass, we will cover it in section 5.4 when we try overriding variables to customize a theme.
Like Less, Sass also support 2 ways of commenting:
bc. {color:#295646;}// and
bc. {color:#295646;}/* … */
Sass also support
bc. {color:#295646;}+,
bc. {color:#295646;}-,
bc. {color:#295646;}*,
bc. {color:#295646;}/, for example:
{color:#295646;} bc. {color:#295646;}$size: 14px; $width: 60%; $color: #ff6600;
.text-lg {
font-size: $size * 2;
color: $color / 2;
}
.panel-lg {
width: $width + 20;
color: $color – #112200;
}
pre
is compiled to:
{color:#295646;} bc. {color:#295646;}.text-lg { font-size: 28px; color: #803300; }
.panel-lg {
width: 80%;
color: #ee4400;
}
pre
Same as Less, the following example is from chapter 2.4 we wrote in Less:
{color:#295646;} bc. {color:#295646;}.article { font-family: Arial, sans-serif; > h3 { font-size: 1.4em; margin-bottom: 1.2em; } p { margin-bottom: 1.2em; } } pre
We can just use
bc. {color:#295646;}sass to compile it without any changes, then we can get this:
{color:#295646;} bc. {color:#295646;}.article { font-family: Arial, sans-serif; } .article > h3 { font-size: 1.4em; margin-bottom: 1.2em; } .article p { margin-bottom: 1.2em; } pre
The generated CSS code is also the same as using the
bc. {color:#295646;}lessc command.
In Sass, we use the
bc. {color:#295646;}@mixin directive to define a mixin,
bc. {color:#295646;}@include directive to include its code.
Recall in Less we have:
{color:#295646;} bc. {color:#295646;}.bordered() { border: 1px dotted black; } .panel { background: #e1e1e1; .bordered(); } pre
Now in Sass:
{color:#295646;} bc. {color:#295646;}@mixin bordered() { border: 1px dotted black; } .panel { background: #e1e1e1; @include bordered(); } pre
Sass uses the
bc. {color:#295646;}& symbol to refer parent selector, the same as Less. For example:
{color:#295646;} bc. {color:#295646;}.navbar { background: #333; &-default { .badge { background-color: #fff; } &:hover { background-color: #ff6600; } } } pre
is compiled to:
{color:#295646;} bc. {color:#295646;}.navbar { background: #333; } .navbar-default .badge { background-color: #fff; } .navbar-default:hover { background-color: #ff6600; } pre
Sass provides a list of builtin functions. In chapter 2.7 we introduced some commonly used functions in Less, compare to those, below are functions defined in Sass, which are basically the same in Less:
A quick example:
{color:#295646;} bc. {color:#295646;}$alert-warning-bg: #fcf8e3; $alert-warning-border: darken(adjust-hue($alert-warning-bg, -10), 5%); .alert-warning { background-color: $alert-warning-bg; border: 1px solid $alert-warning-border; } pre
After compilation:
{color:#295646;} bc. {color:#295646;}.alert-warning { background-color: #fcf8e3; border: 1px solid #faebcc; } pre
In Less we use
bc. {color:#295646;}&:extend to share CSS properties with other selectors, in Sass we use the
bc. {color:#295646;}@extend directive instead.
{color:#295646;} bc. {color:#295646;}.btn { background-color: #ff6600; color: #ffffff; } .btn-large { @extend .btn; padding: 5px 10px; font-size: 18px; } pre
After compilation:
{color:#295646;} bc. {color:#295646;}.btn, .btn-large { background-color: #ff6600; color: #ffffff; }
.btn-large {
padding: 5px 10px;
font-size: 18px;
}
pre
Use the
bc. {color:#295646;}@import directive to import code from other
bc. {color:#295646;}.scss file, the filename suffix can be ignored. For example, if we have a variables.scss, and navbar.scss, in navbar.css we can use
bc. {color:#295646;}@import “variables”; to import code defined in variables.scss.
It also works if we rename the file name variables.scss to [variables.scss_] which has a leading underscore, we don’t need to change the
bc. {color:#295646;}@import “variables”; statement. The Sass compiler is smart enough to find the file named [variables.scss_], however, if we have both the variables.scss and [variables.scss_] file, for this
bc. {color:#295646;}@import “variables”; statement, Sass will throw an error:
{color:#295646;} bc. {color:#295646;}Error: It's not clear which file to import for '@import "variables"'. Candidates: _variables.scss variables.scss pre
The file with a leading underscore at its name is called partial Sass file, the underscore lets Sass know that this file should not be compiled and generated to a plain CSS file. So if we just want to import a Sass file, we could add this leading underscore to its name.
h4<{color:#2d5986;}.
bc. {color:#295646;}@if directive
The
bc. {color:#295646;}@if directive will evaluate an expression and use styles under the expression if it is true. For example:
{color:#295646;} bc. {color:#295646;}$enable-rounded: true; @mixin border-radius($radius) { @if $enable-rounded { border-radius: $radius; } }
.panel {
@include border-radius(5px);
}
pre
is compiled to:
{color:#295646;} bc. {color:#295646;}.panel { border-radius: 5px; } pre
You can use
bc. {color:#295646;}@if along with
bc. {color:#295646;}@else, like:
{color:#295646;} bc. {color:#295646;}@if expressionA { ... } @else { ... } pre
and with
bc. {color:#295646;}@else if:
{color:#295646;} bc. {color:#295646;}@if expressionA { ... } @else if expressionB { ... } @ else { ... } pre
If a mixin contains a
bc. {color:#295646;}@content block, we can override it when we include the mixin. For example:
{color:#295646;} bc. {color:#295646;}@mixin aa { .navbar { @content; } } @include aa { .logo { background-image: url(/logo.gif); } } pre
{color:#295646;}@content will be replaced by code:
{color:#295646;} bc. {color:#295646;}.logo { background-image: url(/logo.gif); } pre
So the above code becomes:
{color:#295646;} bc. {color:#295646;}.navbar { .logo { background-image: url(/logo.gif); } } pre
After compilation:
{color:#295646;} bc. {color:#295646;}.navbar .logo { background-image: url(/logo.gif); } pre
h4<{color:#2d5986;}.
bc. {color:#295646;}@each directive
The
bc. {color:#295646;}@each directive can loop through all items in a list. For example:
{color:#295646;} bc. {color:#295646;}@each $icon in (user, badge, trophy) { .icon-#{$icon} { background:url('../images/#{$icon}.png'); } } pre
is compiled to:
{color:#295646;} bc. {color:#295646;}.icon-user { background: url("../images/user.png"); } .icon-badge { background: url("../images/badge.png"); } .icon-trophy { background: url("../images/trophy.png"); } pre
It can also loop through a map (key-value pair structure) with
bc. {color:#295646;}map-keys and
bc. {color:#295646;}map-get function:
{color:#295646;} bc. {color:#295646;}$size-value: ( xs: 5px, sm: 10px, md: 15px ); @each $size in map-keys($size-value) { .padding-#{$size} { padding: map-get($size-value, $size); } } pre
The
bc. {color:#295646;}map-keys return a list of the map’s keys,
bc. {color:#295646;}map-get can get a key’s value from a map, so the above code is compiled to:
{color:#295646;} bc. {color:#295646;}.padding-xs { padding: 5px; } .padding-sm { padding: 10px; } .padding-md { padding: 15px; } pre
h4<{color:#2d5986;}.
bc. {color:#295646;}@for directive
The
bc. {color:#295646;}@for directive can help repeatedly generate a set of styles with a counter variable, for example:
{color:#295646;} bc. {color:#295646;}@for $i from 1 through 3 { .padding-#{$i} { padding: 5px * $i; } } pre
Here the
bc. {color:#295646;}$i is our counter variable, its initial value is 1, then 2 and 3. So after compilation:
{color:#295646;} bc. {color:#295646;}.padding-1 { padding: 5px; } .padding-2 { padding: 10px; } .padding-3 { padding: 15px; }
pre
{color:#295646;} bc. {color:#295646;}$ sass variables.scss variables.css pre
Bootstrap 4 has similar structure as Bootstrap 3, it contains the following folders:
Compared to Bootstrap 3, you may notice that the fonts folder is gone, since Bootstrap 4 doesn’t use the Glyphicons font anymore, and suggests us to use them from other sources like FontAwesome (http://fontawesome.io/). Among the above folders, we will focus on the scss since our customization work will mainly rely on the CSS part, other folder or files like Gruntfile.js, bower.json , etc., are related to building or shipping this package, so we can ignore them for now.
Under the scss folder, there are 39 .scss files and 2 folders:
The first 36 .scss files with leading underscore in their filenames can be divided into 6 groups:
Below 4 files define components that work with Javascript:
File [utilities.scss_] imports all 13 scss files under the utilities folder, those 13 files define all of the util classes:
We mentioned that the bootstrap.scss file is the one used to generate compiled CSS file, so let’s try compiling it:
{color:#295646;} bc. {color:#295646;}$ sass bootstrap.scss bootstrap.css pre
{color:#295646;} bc. {color:#295646;}<link rel="stylesheet" href="/bootstrap-4.0.0-alpha.6/dist/css/bootstrap.css"/> pre
to:
{color:#295646;} bc. {color:#295646;}<link rel="stylesheet" href="/bootstrap-4.0.0-alpha.6/scss/bootstrap.css"/> pre
Notice that now we are using our own compiled bootstrap 4 CSS file.
In this section we are going to make a simple theme for Bootstrap 4. Remember no matter which version it is, the method for building a theme is essentially the same: override those default CSS rules. This also means the methods in previous chapters we learned to make themes for Bootstrap 3 could also be applied for Bootstrap 4.
In the last section we mentioned that in Bootstrap 4’s source code, there is an empty file named [custom.scss_], Bootstrap 4 provides this file as a “hook” so we can override some variables in this file when we do the customization. So let’s try to redefine some variables in this file.
Which variable should we choose to override? The easiest way would be, override the
bc. {color:#295646;}$enable-* variables, by that I mean, if we check the [variables.scss_] file, there are 7
bc. {color:#295646;}$enable-* variables, listed below:
{color:#295646;} bc. {color:#295646;}$enable-rounded: true !default; $enable-shadows: false !default; $enable-gradients: false !default; $enable-transitions: true !default; $enable-hover-media-query: false !default; $enable-grid-classes: true !default; $enable-print-styles: true !default; pre
These variables are like switches, for example, by default we can see a lot of components in Bootstrap 4 have rounded corners, those rounded corner are actually controlled by the
bc. {color:#295646;}$enable-rounded variable, or we call it “switch”. From the above 7 variables we can see the default theme basically enabled rounded corners, disabled gradient effects, disabled shadow effects, enabled transition animations, etc.
You must have guessed that we could just redefine those “switch” variables’ values to easily generate a theme, so let’s try it.
In this book’s repo, go to folder bootstrap-4.0.0-alpha.6/scss, open [custom.scss_] file with your favorite editor, this file doesn’t have any content except some comments for now, let’s redefine 2 variables:
{color:#295646;} bc. {color:#295646;}$enable-rounded: false; pre
You can see here we are trying to disable the rounded corners, let’s compile it, in this scss folder, start a command/terminal window, then run the command:
{color:#295646;} bc. {color:#295646;}$ sass bootstrap.scss bootstrap.css pre
I already put a theme-styles.html file in folder chapter5/5.4 and added a CSS link to this
bc. {color:#295646;}bootstrap.css file, so after you used the above command to generate the
bc. {color:#295646;}bootstrap.css file, simply go to this book’s repository folder make-bootstrap-themes, open a command/terminal window, use
bc. {color:#295646;}http-server command to start a web server, then open the url http://127.0.0.1:8080/chapter5/5.4/theme-styles.html in your browser.
If you compare this page with http://127.0.0.1:8080/chapter5/5.1/theme-styles.html, you can see now all of rounded corners are gone!
Buttons:
Alerts:
Panels/Cards:
Given we only added one line of code to change only one variable, this looks great, we now have the first customized theme of Bootstrap 4!
Please also notice, if you are trying to change the “gradient” variable to enable gradient effects like this:
{color:#295646;} bc. {color:#295646;}$enable-gradients: true; pre
After recompilation and generating the bootstrap CSS file, if you refresh the theme-styles.html page, there isn’t any change, components like buttons still don’t have a gradient background color. A reasonable guess is, this version bootstrap-4.0.0-alpha.6 doesn’t support all of those switch variables yet, so this might work when bootstrap 4 is officially released.
In this part we are going to override more variables like we did in chapter 3.4, but before we do it, we need to learn a major difference between Sass and Less, which will help us to do the overriding.
Let’s check the following Less code for example:
{color:#295646;} bc. {color:#295646;}@color: #ff6600; @brand-primary: @color;
p {
color: @brand-primary;
}
@color: #339900;
pre
We first define the
bc. {color:#295646;}@color variable, and let the
bc. {color:#295646;}@brand-primary refer the value of
bc. {color:#295646;}@color, then in the CSS of the
bc. {color:#295646;}p tag, we set its color to be
bc. {color:#295646;}@brand-primary. In the last line we redefine the value of
bc. {color:#295646;}@color to be
bc. {color:#295646;}#339900. After compilation with
bc. {color:#295646;}lessc, we have the following code:
{color:#295646;} bc. {color:#295646;}p { color: #339900; } pre
Notice that the color of
bc. {color:#295646;}p is
bc. {color:#295646;}#339900.
Now let’s write the same code with Sass syntax:
{color:#295646;} bc. {color:#295646;}$color: #ff6600; $brand-primary: $color;
p {
color: $brand-primary;
}
$color: #339900;
pre
This time after compilation with Sass, we have:
{color:#295646;} bc. {color:#295646;}p { color: #ff6600; } pre
Now the color of
bc. {color:#295646;}p is
bc. {color:#295646;}#ff6600, we are trying to override
bc. {color:#295646;}$color’s value in the last line and
bc. {color:#295646;}$brand-primary refers to this
bc. {color:#295646;}$color, but apparently
bc. {color:#295646;}p is still using the previous color
bc. {color:#295646;}#ff6600, not the new one
bc. {color:#295646;}#339900, this is different with code generated by Less.
It turns out Less and Sass are using different ways to generate variables’ values. In Less, it first collects all variables’ values, then generates the final value for each variable, if there are multiple definitions for the same variable, the last one wins. In the above example, once Less collects all variables,
bc. {color:#295646;}@color is set to be
bc. {color:#295646;}#339900, then the
bc. {color:#295646;}@brand-primary will also set to be
bc. {color:#295646;}#339900, thus, the color of the
bc. {color:#295646;}p tag is set to
bc. {color:#295646;}#339900. While Sass uses a different methodology, it won’t first collect all variables to decide their final values, instead, it uses “first come, first serve” method: when it scans to
bc. {color:#295646;}$brand-primary, its value is already defined as the first
bc. {color:#295646;}$color’s value
bc. {color:#295646;}#ff6600, later we redefine
bc. {color:#295646;}$color to be
bc. {color:#295646;}#339900, but it will not change the
bc. {color:#295646;}$brand-primary’s value, so the color of the
bc. {color:#295646;}p tag is still
bc. {color:#295646;}#ff6600.
Let’s see another example, suppose we have the following code in Less:
{color:#295646;} bc. {color:#295646;}@color: #ff6600; p { color: @color; }
color: #339900;
h1 {
color:
color;
}
pre
Compiled to:
{color:#295646;} bc. {color:#295646;}p { color: #339900; } h1 { color: #339900; } pre
Notice both
bc. {color:#295646;}p and
bc. {color:#295646;}h1 use the color
bc. {color:#295646;}#339900, which means Less first collects all variables and finds that the final value of
bc. {color:#295646;}@color is
bc. {color:#295646;}#339900, so it uses this value in every place where
bc. {color:#295646;}@color appears.
Now let’s try the same code in Sass:
{color:#295646;} bc. {color:#295646;}$color: #ff6600; p { color: $color; }
$color: #339900;
h1 {
color: $color;
}
pre
Compiled to:
{color:#295646;} bc. {color:#295646;}p { color: #ff6600; } h1 { color: #339900; } pre
Notice now the
bc. {color:#295646;}p tag is using color
bc. {color:#295646;}#ff6600, while the
bc. {color:#295646;}h1 tag is using
bc. {color:#295646;}#339900, which means Sass uses the former definition when it generates code for
bc. {color:#295646;}p. This is because it doesn’t first scan all the variables, it doesn’t know we will redefine
bc. {color:#295646;}$color later, when it generates code for the
bc. {color:#295646;}p tag, at that time
bc. {color:#295646;}#ff6600 is
bc. {color:#295646;}$color’s value. Then on the next line we override
bc. {color:#295646;}$color to be
bc. {color:#295646;}#339900, which means that now
bc. {color:#295646;}$color’s value is
bc. {color:#295646;}#339900, so the next
bc. {color:#295646;}h1 tag uses this value.
How would this affect our overriding for Bootstrap 4? Well, in last section we mentioned in this version v4.0.0-alpha.6, Bootstrap 4 imports first 3 files in this order:
{color:#295646;} bc. {color:#295646;}@import "variables"; @import "mixins"; @import "custom"; pre
The [custom.scss_] file is the one Bootstrap wants us to use to override some variables, but it comes after
bc. {color:#295646;}@import “variables”. In the [variables.scss_] file we have code like this:
{color:#295646;} bc. {color:#295646;}$brand-primary: #0275d8 !defafult; $btn-primary-bg: $brand-primary !default; pre
Notice this
bc. {color:#295646;}$btn-primary-bg is the background color for
bc. {color:#295646;}.btn-primary class, and if we want to change
bc. {color:#295646;}$brand-primary’s color value, we may add the following code to [custom.scss_] file to override its color:
{color:#295646;} bc. {color:#295646;}$brand-primary: #3B4A6B; pre
Apparently when we override this value, we want to change all of the places referring this
bc. {color:#295646;}$brand-primary color, like the background color of
bc. {color:#295646;}.btn-primary class. However, since in this v4.0.0-alpha.6 version, Bootstrap imports [variables.scss_] first then imports the [custom.scss_], those above variables’ order will be like this:
{color:#295646;} bc. {color:#295646;}$brand-primary: #0275d8 !defafult; $btn-primary-bg: $brand-primary !default; // use $brand-primary here, its value is #0275d8 ... $brand-primary: #3B4A6B; // use $brand-primary here, now it is #3B4A6B // use $btn-primary-bg here, now it is still #0275d8 pre
If we use
bc. {color:#295646;}sass to compile the code, we can see the value of
bc. {color:#295646;}$btn-primary-bg is still
bc. {color:#295646;}#0275d8, not
bc. {color:#295646;}#3B4A6B. We want to change all places where use this
bc. {color:#295646;}$brand-primary variable, and places where refer to it, like
bc. {color:#295646;}$brand-primary-bg, but clearly Sass won’t do it in this way.
There are several ways to solve this problem, the first one is, when we override the
bc. {color:#295646;}$brand-primary’s value, also override all variables referring it, in the above example, after we define
bc. {color:#295646;}$brand-primary, we need to also explicitly redefine the
bc. {color:#295646;}$btn-primary-bg, so in our [custom.scss_] we have:
{color:#295646;} bc. {color:#295646;}$brand-primary: #3B4A6B; $btn-primary-bg: $brand-primary; pre
This will override
bc. {color:#295646;}$btn-primary-bg’s value, so the background color of
bc. {color:#295646;}.btn-primary class will now change to
bc. {color:#295646;}#3B4A6B, but this way is cumbersome and infeasible: we need to override all variables referring to it, like
bc. {color:#295646;}$link-color,
bc. {color:#295646;}$pagination-active-bg, etc.
The second way is, we can change the importing order in Bootstrap.scss file: first import the [custom.scss_] file, then the [variables.scss_]:
{color:#295646;} bc. {color:#295646;}@import "custom"; @import "variables"; @import "mixins"; ... pre
In this case, if we define
bc. {color:#295646;}$brand-primary: #3B4A6B in [custom.scss_], the later code
bc. {color:#295646;}$brand-primary: #0275d8 !defafult in [variables.scss_] won’t override it, because there is a
bc. {color:#295646;}!default keyword (if you forgot what it is, check the variables section in chapter 5.2), then the later code
bc. {color:#295646;}$btn-primary-bg: $brand-primary; will set
bc. {color:#295646;}$btn-primary-bg’s value to be
bc. {color:#295646;}#3B4A6B , so
bc. {color:#295646;}.btn-primary class will use our custom color as its background color.
By just switching the importing order in Bootstrap.scss, we can solve the problem, but I am trying to avoid modifying its source code to do the customization. After all, this problem should be fixed by Bootstrap. (Update: at the time of writing this book, Bootstrap 4’s current v4-dev branch already fixed it, we can expect in its future release v4.0.0-alpha.7 or v4-beta, this importing order will be changed.)
If we don’t change the importing order, the third way is, let’s forget this [custom.scss_] hook file, we will just leave it empty, but we will create a new file my-theme.scss, in this file we first redefine variables, then import bootstrap.scss:
{color:#295646;} bc. {color:#295646;}$brand-primary: #3B4A6B; @import "bootstrap"; pre
Like the second way, we make sure our custom values show first, then Bootstrap’s default value in [variables.scss_] will not override it since it uses the
bc. {color:#295646;}!default keyword.
I’ll use the last method to do our customization: go to code repo’s folder chapter5/5.4, open the file my-theme.scss, you will see something like this:
{color:#295646;} bc. {color:#295646;}@import url('https://fonts.googleapis.com/css?family=Roboto+Slab'); $font-family-serif: 'Roboto Slab', Georgia, "Times New Roman", serif; $font-family-base: $font-family-serif;
$enable-rounded: false;
// brand contextual colors
$brand-primary: #3B4A6B;
$brand-success: #52D681;
$brand-info: #22B2DA;
$brand-warning: #FFC24A;
$brand-danger: #F23557;
…
@import “../../bootstrap-4.0.0-alpha.6/scss/bootstrap”;
pre
I imported a new font named
bc. {color:#295646;}Roboto Slab from Google font as my theme’s default font, disabled rounded corners and refined some brand contextual colors, in last line I imported bootstrap’s scss source file.
What does this theme look like? Practice time!
{color:#295646;} bc. {color:#295646;}$ sass my-theme.scss my-theme.css pre
This will generate my-theme.css file.
{color:#295646;} bc. {color:#295646;}<link rel="stylesheet" href="my-theme.css"/> pre
Here are some screenshots for this theme:
Buttons:
Alerts:
Panels/Cards:
In this section we covered the way to override variables for Bootstrap 4, we will end here and won’t go further since Bootstrap 4 is still under active development, the method we introduced here might have changed when Bootstrap 4 is officially released. But to do customization, the key idea is the same: we need to find a way to override its default styles. Thus, the method we learned in chapters 3 and 4 can also be applied here for Bootstrap 4. Now it is your practice time to create your own themes.
In chapter 2 we introduced the
bc. {color:#295646;}lightness,
bc. {color:#295646;}darken,
bc. {color:#295646;}hsl functions in Less, to recap, when we pass a RGB color to the
bc. {color:#295646;}lightness function, it first converts this RGB color to the HSL color space, then changes the lightness channel’s value, and finally changes it back to RGB color, so in this process the conversion happens between the RGB and HSL color spaces.
The conversion requires some calculations, for the algorithm details, I included
bc. {color:#295646;}rgb2hsl and
bc. {color:#295646;}hsl2rgb functions in this book’s example code (written in Javascript), you can check them at code repository file appendix/color_conversion.js.
Moreover, in chapter 2 we used an example: Less increases the lightness of the color
bc. {color:#295646;}#be4c0f by 15% to color
bc. {color:#295646;}#ee6f2b , let’s reproduce it with our own
bc. {color:#295646;}rgb2hsl and
bc. {color:#295646;}hsl2rgb functions:
{color:#295646;} bc. {color:#295646;}let color = '#be4c0f'; let rgb = hex2rgb(color); let hsl = rgb2hsl(rgb.r, rgb.g, rgb.b); console.log('To HSL color space: ', hsl);
// increase lightness by 15%
hsl.l += 0.15;
console.log(‘Add 15% lightness: ‘, hsl);
// convert HSL back to RGB
rgb = hsl2rgb(hsl.h, hsl.s, hsl.l);
console.log(‘To RGB color space: ‘, rgb);
console.log(‘Color hex code is: ‘, rgb2hex(rgb.r, rgb.g, rgb.b));
pre
Output:
{color:#295646;} bc. {color:#295646;}To HSL color space: { h: 20.91, s: 0.85, l: 0.4 } Add 15% lightness: { h: 20.91, s: 0.85, l: 0.55 } To RGB color space: { r: 238, g: 111, b: 43 } Color hex code is: #ee6f2b pre
We can see by using the functions defined in the above file, we successfully changed color
bc. {color:#295646;}#be4c0f to
bc. {color:#295646;}#ee6f2b by increasing its lightness by 15%, which is exactly the same as we did in chapter 2 with Less’s
bc. {color:#295646;}lightness function.
Website: http://getbootstrap.com
If you are looking for documentations on some old versions of Bootstrap, this website can help: http://bootstrapdocs.com/
Bootstrap’s source code: https://github.com/twbs/bootstrap
Version 3.3.7: https://github.com/twbs/bootstrap/tree/v3.3.7
Version 4.0.0-alpha.6: https://github.com/twbs/bootstrap/tree/v4.0.0-alpha.6
Bootstrap 4 code migration guideline:
https://v4-alpha.getbootstrap.com/migration/
Additional showcases and add-ons: https://expo.getbootstrap.com/resources/
Website: http://lesscss.org/
Source code: https://github.com/less/less.js
Online converter: http://less2css.org/
Website: http://sass-lang.com/
Source code: https://github.com/sass/sass
Online converter: https://www.sassmeister.com/
Bootstrap’s Glyphicons contains a limited icon set. Sometimes we may use glyphicons from other websites like:
The above 2 websites contains hundreds of icons, they can meet our needs in most cases. You can also try the GlyphSearch website: http://glyphsearch.com/, which helps search icons from a bunch of resources, including font-awesome, ion-icons, foundation-icons, etc.
Bootswatch (http://bootswatch.com/) provides several themes for free:
You can download its source code at https://github.com/thomaspark/bootswatch , check the source code to learn how those themes are made.
You can also download some free themes at StartBootstrap https://startbootstrap.com/
In our themes often we need some images as placeholders, e.g. user’s avatar picture in media component, pictures used as banner image, pictures in the carousel component, etc. Here are some websites you can use:
When you design a new theme, usually you need to first pick some colors for it, you may already have your own palette if you are an experienced designer, but if you don’t have any, the websites below may give you some inspiration:
In chapter 4.3 we introduced some plugins for Bootstrap, here are some more:
If you are creating a theme or template for an admin page, you may need Javascript to create charts in some “dashboard” page, here are some Javascript libraries you can use to do it:
If you want to explore more, people keep submitting new resources in the Bootstrap-expo page: https://github.com/twbs/bootstrap-expo/issues
If you want to sell your themes to marketplaces, here are some popular ones:
Bootstrap perhaps is the most popular frontend framework for developing mobile first projects on the web in recent years, its repository on github gets more than 100 thousands stars. Millions of websites are using it not only because it is easy to learn and use but the flexibility of customization. In this book, we’ll focus on the customization part - build your own Bootstrap theme. At the time of writing this book, Bootstrap 4 is still in its alpha version, by “Bootstrap†here we are referring to Bootstrap 3. We will start with preparing a development workbench, and introducing Less (a CSS pre-processor Bootstrap uses), then walk through Bootstrap’s source code which will help us first get familiar with its code structure and later build themes by reusing it. Moreover, we will learn how to make additional styles and use plugins to polish our themes. Lastly we will touch on Bootstrap 4 a little and see how to use and customize it. This book is not an introduction to how to use Bootstrap, nor is it for learning the basics of HTML, CSS and Javascript. For example, you should know what "container", "col-xs-12", "col-sm-10" classes mean in Bootstrap. If not, I suggest reading through some tutorials about using Bootstrap before coming back to this book. If you are already familiar with the basis of HTML, CSS and Bootstrap usage, and want to go further to customize its theme, or even sell your own theme in the marketplaces, this is the book for you.