
Jade is an HTML preprocessor and templating engine that was written in JavaScript for Node.js. Simply put, Jade is exactly the tool that gives you the ability to write your markup in a completely new way, with
a number of advantages over regular HTML. For example, take a look at the HTML code below:
<div> <h1>Ocean's Eleven</h1> <ul> <li>Comedy</li> <li>Thriller</li> </ul> <p>Danny Ocean and his eleven accomplices plan to rob three Las Vegas casinos simultaneously.</p> </div>
And so this markup looks in Jade format:
div h1 Ocean's Eleven ul li Comedy li Thriller p. Danny Ocean and his eleven accomplices plan to rob three Las Vegas casinos simultaneously.
The second option seems shorter and more elegant. But Jade is not only a pretty markup. Jade has some really useful functions that allow you to write modular reusable (reusable) code. But before going deep, let's review the basics.
The basics
I'm going to highlight the three main features of Jade:
- Simple tags;
- Add attributes to tags;
- Blocks of text.
If you want to read the article, try out the code samples below, you can use
CodePen and choose Jade as a preprocessor for your HTML, or use the
online compiler on the official Jade website .
')
Tags
As you can see earlier, there are no closing tags in Jade. Instead, Jade uses tabs to define tag nesting.
div p Hello! p World!
In the example above, the paragraph tags according to their tabulation when compiled will end up inside the div tag. How simple!
<div> <p>Hello!</p> <p>World!</p> </div>
Jade compiles this accurately, treating the first word on each line as a tag, while subsequent words on this line are treated as text inside the tag.
View this CodePen exampleAttributes
All this, of course, is good, but how to add attributes to our tags? Actually quite simple.
Let's go back to our first example and add a couple of classes and a certain poster picture.
div(class="movie-card", id="oceans-11") h1(class="movie-title") Ocean's 11 img(src="/img/oceans-11.png", class="movie-poster") ul(class="genre-list") li Comedy li Thriller
How wonderful, isn't it?
<div class="movie-card" id="oceans-11"> <h1 class="movie-title">Ocean's 11</h1> <img src="/img/oceans-11.png" class="movie-poster"> <ul class="genre-list"> <li>Comedy</li> <li>Thriller</li> </ul> </div>
View this CodePen exampleBut why stop there? Jade provides special shorthand for indifiers and classes, which further simplifies our markup using familiar notations:
div.movie-card#oceans-11 h1.movie-title Ocean's 11 img.movie-poster(src="/img/oceans-11.png") ul.genre-list li Comedy li Thriller
View this CodePen exampleAs you can see, Jade uses similar syntax to the one you use when writing CSS selectors.
Text blocks
Let's imagine this situation: you have a <p> tag and you want to add quite a large amount of text to it. But wait, Jade treats the first word of each line as a new HTML tag - and how to be here?
In the very first example, you might have noticed a nondescript point after a paragraph tag. Adding a dot after your tag makes it clear to the Jade compiler that everything inside this tag is text.
div p How are you? p. I'm fine thank you. And you? I heard you fell into a lake? That's rather unfortunate. I hate it when my shoes get wet.
View this CodePen exampleFor the sake of clarity: if I didn’t put a dot after the <p> tag in the example, then the compiled HTML would have the open <i> tag inside it, breaking the phrase “I'm” at the beginning of the line.
Useful features
Now that we’ve dealt with the basics, let's look at some really useful features that will make our markup smarter. Among them:
- Javascript;
- Cycles;
- Interpolation;
- Mixins
Jade javascript
Jade is implemented in JavaScript, so using Jade in JavaScript is quite simple. Here is an example:
- var x = 5; div ul - for (var i=1; i<=x; i++) { li Hello - }
What have we done here ?! Starting the line with a hyphen, we indicated to the Jade compiler that we can use JavaScript, and that’s how it works! And this is what we get when we compile this code in HTML:
<div> <ul> <li>Hello</li> <li>Hello</li> <li>Hello</li> <li>Hello</li> <li>Hello</li> </ul> </div>
View this CodePen exampleWe use a hyphen when the code should not directly fall into the output stream. In the case, if we want to use JavaScript to display something in Jade, we use
= . Let's correct the code above to indicate the numbering of the elements in the list:
- var x = 5; div ul - for (var i=1; i<=x; i++) { li= i + ". Hello" - }
And voila, we have numbering:
<div> <ul> <li>1. Hello</li> <li>2. Hello</li> <li>3. Hello</li> <li>4. Hello</li> <li>5. Hello</li> </ul> </div>
View this CodePen exampleOf course, in this case a numbered list would be much more appropriate, but did you catch the idea? For more information, read the
documentation .
Cycles
Jade uses great syntax to write loops, so you don’t have to resort to JavaScript. Let's go through the array elements in a loop:
- var droids = ["R2D2", "C3PO", "BB8"]; div h1 Famous Droids from Star Wars for name in droids div.card h2= name
And it will be compiled as follows:
<div> <h1>Famous Droids from Star Wars</h1> <div class="card"> <h2>R2D2</h2> </div> <div class="card"> <h2>C3PO</h2> </div> <div class="card"> <h2>BB8</h2> </div> </div>
View this CodePen exampleYou can navigate through the array objects, as well as use the while loop. Find out more by reading the
documentation .
Interpolation
Combine text and javascript in this way
p = "Hi there," + profileName + ". How are you doing?"
may begin to exaggerate your eyes. Doesn't Jade have a more elegant solution to this problem? Let us argue?
- var profileName = "Danny Ocean"; div p Hi there, #{profileName}. How are you doing?
View this CodePen exampleIsn't that so neat?
Mixins
Mixins, they are like functions, they take parameters as input and generate the appropriate markup. Mixins are advertised using the
mixin keyword.
mixin thumbnail(imageName, caption) div.thumbnail img(src="/img/#{imageName}.jpg") h4.image-caption= caption
After the mixin has been announced, you can call it using the
+ symbol.
+thumbnail("oceans-eleven", "Danny Ocean makes an elevator pitch.") +thumbnail("pirates", "Introducing Captain Jack Sparrow!")
What will be compiled as:
<div class="thumbnail"> <img src="/img/oceans-eleven.jpg"> <h4 class="image-caption"> Danny Ocean makes an elevator pitch. </h4> </div> <div class="thumbnail"> <img src="/img/pirates.jpg"> <h4 class="image-caption"> Introducing Captain Jack Sparrow! </h4> </div>
Putting it all together
Let's collect everything that we managed to learn, in one example. Let's say we have an array of films, each object of which contains the name of the film, the cast (sub-array), rating, genre, a link to the IMDB page and the path to the picture (which will be used as a movie poster). The array will look something like this:
- var movieList = [ { title: "Ocean's Eleven", cast: ["Julia Roberts", "George Clooney", "Brad Pitt", "Andy Garcia"], genres: ["Comedy", "Thriller"], posterImage: "/img/oceans-eleven", imdbURL: "http://www.imdb.com/title/tt0240772/", rating: 7 } // etc... ];
We have 10 films and we want to make a nice markup for each of them. Initially, we did not use the link to the IMDB page of the film. If the rating of the film is higher than 5, we give it an icon with the thumb raised upwards, otherwise, the thumb is down. We use all of the above useful Jade functions to write this modular code that performs the following tasks:
- Create a mixin called movie-card
- Enumerate the array and display the cast.
- Enumerate array and display genres.
- Check the rating of the film and assign it the appropriate icon.
- Pick an array of movies and use mixin to create markup.
And so, let's create a mixin:
mixin movie-card(movie) div.movie-card h2.movie-title= movie.title img.movie-poster(src=movie.posterImage) h3 Cast ul.cast each actor in movie.cast li= actor div.rating if movie.rating > 5 img(src="img/thumbs-up") else img(src="img/thumbs-down") ul.genre each genre in movie.genres li= genre
In this code, a lot of things are happening, but I am sure that you understand it, since we have already passed this. Now, all we need is to call this mixin in a loop:
for movie in movieList +movie-card(movie)
And that's it! Isn't that cool ?! Here is the final code:
- var movieList = [ { title: "Ocean's Eleven", cast: ["Julia Roberts", "George Clooney", "Brad Pitt", "Andy Garcia"], genres: ["Comedy", "Thriller"], posterImage: "/img/oceans-eleven", imdbURL: "http://www.imdb.com/title/tt0240772/", rating: 9.2 }, { title: "Pirates of the Caribbean", cast: ["Johnny Depp", "Keira Knightley", "Orlando Bloom"], genres: ["Adventure", "Comedy"], posterImage: "/img/pirates-caribbean", imdbURL: "http://www.imdb.com/title/tt0325980/", rating: 9.7 } ]; mixin movie-card(movie) div.movie-card h2.movie-title= movie.title img.movie-poster(src=movie.posterImage) h3 Cast ul.cast each actor in movie.cast li= actor div.rating if movie.rating > 5 img(src="img/thumbs-up") else img(src="img/thumbs-down") ul.genre each genre in movie.genres li= genre for movie in movieList +movie-card(movie)
And so the code will look after compilation:
<div class="movie-card"> <h2 class="movie-title">Ocean's Eleven</h2> <img src="/img/oceans-eleven" class="movie-poster"/> <h3>Cast</h3> <ul class="cast"> <li>Julia Roberts</li> <li>George Clooney</li> <li>Brad Pitt</li> <li>Andy Garcia</li> </ul> <div class="rating"> <img src="img/thumbs-up"/> </div> <ul class="genre"> <li>Comedy</li> <li>Thriller</li> </ul> </div> <div class="movie-card"> <h2 class="movie-title">Pirates of the Carribean</h2> <img src="/img/pirates-caribbean" class="movie-poster"/> <h3>Cast</h3> <ul class="cast"> <li>Johnny Depp</li> <li>Keira Knightley</li> <li>Orlando Bloom</li> </ul> <div class="rating"> <img src="img/thumbs-up"/> </div> <ul class="genre"> <li>Adventure</li> <li>Comedy</li> </ul> </div>
But stop, wait a minute! But what if now we need the ability to go to the IMDB-page of the movie by clicking on its name? We just need to add one line.
a (href = movie.imdbURL)
in our mixin.
mixin movie-card(movie) div.movie-card a(href=movie.imdbURL) h2.movie-title= movie.title img.movie-poster(src=movie.posterImage) h3 Cast ul.cast each actor in movie.cast li= actor div.rating if movie.rating > 5 img(src="img/thumbs-up") else img(src="img/thumbs-down") ul.genre each genre in movie.genres li= genre
View this CodePen exampleConclusion
Today we have gone from the complete ignorance of the Jade preprocessor to writing, with its help, excellent modular markup. This is not all that Jade can do, but I hope that this article has touched your curiosity and you want to learn more.
Important note: as some of you may already know, Jade has been renamed Pug. In the future, articles about Jade will use the new name “Pug” or “Pug.js”.