codete Tailwind CSS Tutorial and Examples for Beginners 1 main a6e066559d
Codete Blog

Tailwind CSS Tutorial and Examples for Beginners

Bartosz Szewczyk 362d896fa9

20/01/2022 |

22 min read

Bartosz Szewczyk

Tailwind CSS tutorial as well as Tailwind CSS examples are something that may turn out to be very useful for beginners who want to master the basics of this utility-first CSS framework. But not only for them. 

Building captivating website designs with it may be a tough nut to crack in the beginning so if you want to learn Tailwind CSS fast, it’s good to read our detailed guide. As a part of the Tailwind tutorial, some interesting Tailwind examples will also be provided. So if you’re interested in learning Tailwind get started with us soon.

 

In this extensive Tailwind tutorial, the following threads will be discussed:

1. Tailwind CSS in a nutshell

2. Tailwind CSS tutorial and examples

3. Now you know how to use Tailwind CSS in your projects

TailwindCSS in a nutshell

Tailwind is a CSS framework that helps developers to start a new project with a set of utility styles to quickly and easily make beautiful and scalable web applications. CSS frameworks are still a popular utensil in the frontend toolbelt, and there are plenty of good reasons for that.

First of all – native HTML elements are far from pretty and sometimes it requires a lot of CSS to make the web pages appealing and responsive. CSS frameworks help developers to start with a basic set of rich and customizable styles for different components, usually with a mobile-first approach. 

Mobile-first means that the page is created with mobile devices screen size in mind and its layout is incrementally adjusted for higher resolutions. This way of designing web pages is considered by many to be a much easier way of writing applications than starting with the layout for desktop resolutions, and then squeezing the page to fit the smaller screens.

Why use CSS frameworks?

If we don’t have a design system, CSS frameworks can give us a nice set of building blocks to make applications visually elegant. Internal admin panels are often the case of such applications. The features are more important than the looks, and they usually don’t have any designs at all. If they are built using a CSS framework, a frontend developer can easily create visibly pleasant web applications.

Similarly, if we need to create a simple page showcasing a single component or functionality, create a small application for a hackathon or work on a side-project after hours it’s good to have a ready-to-use solution for fast and pretty styling. If you were tasked with creating a web application as a part of the interview process the looks of the app may mean as much if not more than the code itself and the functionality.

On the other hand, if we’re creating a new application in a team with dedicated UX designers, the design usually requires a lot of work to implement. Setting up the theme which may consist of spaces, colors, grids and all of that for different screen resolutions is by no means an easy feat. Because of CSS frameworks’ customizability, they can be used as a backbone to build the desired outcome faster and more efficiently.

Utility-first CSS framework

Tailwind CSS is a collection of utility classes, each of which is responsible for some small functionality. This could be text color, background color, spacing, or borders. Such an approach allows us to write a page based on the so-called atomic CSS. It is a method that currently has as many supporters as opponents. And software developers are used to writing and designing CSS in projects using the component approach. Let's first explain what the two approaches are, to better understand their differences.

In the component approach to writing CSS, each component (an element with a specific functionality such as select, a rich-text box, or a carousel with images) should be independent in terms of its HTML, JavaScript code, and styles. The styles of one component should not affect the appearance of another component in any way. Writing CSS like this is very convenient and intuitive for software developers. However, this solution has its drawbacks.

Because CSS works globally, we need to write class names in a way that makes avoiding potential conflicts possible. We cannot have two different components that define the `carousel` class. There are a number of solutions that allow us to generate unique class names so that the styles are not accidentally overwritten. Thankfully, we’ve recently got a great feature in browsers called ShadowDOM – a way to create styles that are completely isolated from each other. Unfortunately, even when we subtract the problem with potential name conflicts the component approach has another, more serious, problem. It is related to application development. Because we care about class uniqueness, our CSS files grow larger and larger as the number of components increases and the number of their variants multiplies.

In the atomic approach to writing CSS, we have many classes controlling only small aspects of the appearance. The classes are predefined and clearly named, and with a documented arsenal of them, we assign a select few to specific elements.

For many developers, the approach that Tailwind CSS promotes seems strange and unjustified. Often it is wrongly accused that the multitude of classes will cause the final size of submitted CSS together with HTML to be too large, and the management of them will turn out to be complex and impractical. Meanwhile, there is no shortage of opinions that the exact opposite is true. Many people, after trying Tailwind CSS, find its methodology very easy to use. Since the new components that we write can use mostly existing classes, it turns out that CSS files grow more slowly and less aggressively than in the traditional approach.

Tailwind CSS – features and restrictions

This article was written based on the latest version of Tailwind CSS 3.0.5. Many of the CSS classes it provides utilize features only present in new browsers, such as `filter`, `aspect-ratio`, and `:focus-within`. There are many ways to replicate some of these using various workarounds and hacks, but the end result may not be the same as what browsers natively offer. That is why you should always make sure that your website will look the same on all browsers utilized by the users of the applications you are creating. You can check a recommended database of functions implemented in particular versions of browsers on the Can I Use website.

Starting with version 2.0.0, Tailwind no longer supports old browsers such as Internet Explorer 11. If we are working on a project that needs to look equally good on them, we have to use an older version of Tailwind 1.9.0, but you have to reckon with the fact that not all features described in this article are implemented there.

Tailwind CSS tutorial and examples

Let's see how the same component can look from the code side written in different styles:

card component 67902d3fae

A simple card component, with an image and text inside. When you hover the mouse over it, the background color changes.

First, let's see what styling such an element might look like traditionally. Let's define a class for each element – card, image, and text and then assign them to HTML elements. In this example, colors and spacing have been specifically chosen to match those available in Tailwind CSS.

<style>

  .card {

    border-radius: 0.375rem;

    border: 1px solid rgb(115, 115, 115);

    background-color: rgb(64, 64, 64);

    transition: background-color 150ms cubic-bezier(0.4, 0, 0.2, 1);

    color: rgb(245, 245, 245);

    display: flex;

    flex-direction: row;

    align-items: flex-start;

    cursor: pointer;

  }



  .card:hover {

    background-color: rgb(82, 82, 82);

  }



  .card-img {

    padding: 1rem 0rem 1rem 1rem;

    align-items: center;

    aspect-ratio: 1 / 1;

  }



  .card-contents {

    line-height: 1rem;

    margin: 0.75rem 1rem;

  }

</style>

<section class="card">

  <img src="http://placekitten.com/100/100" alt="cat" class="card-img" />

  <p class="card-contents">

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod

    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,

    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo

    consequat.

  </p>

</section>

HTML + CSS code that we would have to write manually to style the card with the image.


Now, let's see how we can achieve the same effect using ready-made classes that Tailwind CSS gives us.

<section class="rounded-md border border-neutral-500 bg-neutral-700 hover:bg-neutral-600 transition-colors text-neutral-100 flex flex-row items-start cursor-pointer">

  <img src="http://placekitten.com/100/100" alt="cat" class="py-4 pl-4 aspect-square" />

  <p class="mx-4 my-3 leading-4">

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod

    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,

    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo

    consequat.

  </p>

</section>

The same element written using Tailwind CSS. We don't need a single line of CSS here because we use provided classes.

 

However, if we do not feel convinced to assign a large number of classes to each HTML element, Tailwind also allows us to use it in a component way. If we use the tool it provides, we get access to special directives in CSS files called `@apply` that copy styles from individual classes to a specific selector.

<style>

  .card {

    @apply rounded-md border border-neutral-500 bg-neutral-700  hover:bg-neutral-600 transition-colors text-neutral-100 flex flex-row items-start cursor-pointer;

  }



  .card-img {

    @apply py-4 pl-4 aspect-square;

  }



  .card-contents {

    @apply mx-4 my-3 leading-4;

  }

</style>

<section class="card">

  <img src="http://placekitten.com/100/100" alt="cat" class="card-img" />

  <p class="card-contents">

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod

    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,

    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo

    consequat.

  </p>

</section>

Using the `@apply` directive from Tailwind CSS to create classes that will have styles from the listed utility classes.

As you can see, Tailwind CSS does not force any approach on us and we can use it comfortably and suitably. Nevertheless, the authors of Tailwind CSS recommend using multiple classes and assigning them in HTML, which is an atomic approach.

How to use Tailwind CSS

Tailwind is more than just a collection of CSS classes. It is also a tool that enables us to configure many values like colors or spacing to our needs. It also offers a minifier that scans the use of classes in our HTML, JS, and CSS files and imports only the subset of classes that we use. Thanks to this we don't have to worry that we will send out kilobytes of unused CSS.

To use the tool we need to install a package from the npm registry called `tailwindcss` and use it to create a configuration file. Being inside a project using nodejs, we need to type two commands in the console:

$ npm install -D tailwindcss
$ npx tailwindcss init

The first command installs `tailwindcss` as a dev dependency. The second one launches its init script.

The first one will download the Tailwind CSS library, which has all the classes in it, as well as a handy tool to use them. The second command will create a configuration file called `tailwind.config.js`, which allows us to tailor Tailwind to our needs. The file looks like this:

module.exports = {

  content: [],

  theme: {

    extend: {},

  },

  plugins: [],

}

Empty `tailwind.config.js` file.

 

Now we need to add a path rule to it that matches our HTML and CSS files:

module.exports = {

  content: ["./src/**/*.{html,js}"],

  theme: {

    extend: {},

  },

  plugins: [],

}

`tailwind.config.js` file with content glob pattern.

 

This way Tailwind CSS will know where to look for the usage of its classes. During the build process of our project, only those of the classes that are used anywhere in the `.html` and `.js` files will go into the final CSS file, nothing else will be included. 

Let's assume that the only file in the `src` folder will be the HTML file with the card component we wrote earlier that only uses the classes offered by Tailwind, and doesn't define any other styles. To build a CSS file for this file we need to call the `tailwindcss` command with the following arguments:

npx tailwindcss -o ./dist/output.css

Command to build output CSS files with Tailwind CSS classes that are used.
 

The `-o` option defines the path to the file that Tailwind CSS will build for us. After running the command, when we look in the `output.css` file, we will see that Tailwind CSS first put a lot of CSS code there and only at the end the classes that we used. The purpose of the initial code is to compensate for differences in the display between browsers so that our pages look the same when using native HTML elements. This is a common procedure and is commonly called "normalize". Tailwind specifically uses the modern-normalize library for this. Of course, we can disable the inclusion of this code if we upload it as a standalone file, or we simply don't need this functionality. We just need to add the `corePlugins.preflight` option to the `tailwind.config.js` file as `false`:

module.exports = {
  content: ["./src/**/*.html"],
  corePlugins: { preflight: false },
};

Disable CSS normalize code generation.

 

We can optionally pass an `-m` flag to the command to make the final CSS file minified. Such a file will have all whitespace characters removed so that its size will be much smaller, but the file will no longer be readable by a programmer. Fortunately, we don't have to worry about its readability because in production we want all our CSS files to be as small as possible and it is a normal practice to use the minimized version.

Tailwind CSS also has support for many popular frameworks like Next.js, Gatsby, Laravel, or Create-React-App. On top of that, you can use it as a plugin for the PostCSS library which itself easily integrates with currently used bundlers like webpack or rollup.

One class, many values

Many CSS attributes take numeric values. These are usually the attributes that control the size or spacing between elements. Let's see how Tailwind CSS can be used to add different margins to an element:

ClassProperties
m-0margin: 0px
my-pxmargin-top: 1px; 
margin-bottom: 1px;
mx-2margin-left: 0.5rem;
margin-right: 0.5rem;
ml-8margin-left: 2rem
mr-36margin-right: 9rem

A table of selected margin classes for different box-model sides and different sizes, and their corresponding style properties.my-px

 

The choice of the values shown is random. The table is just to show that the numbers do not directly correspond to the pixel size but refer to an index in the table of defined sizes. We can also note that Tailwind has decided that all sizes (except `px`) use rem units. We can now define a margin assignment formula for the element:

m{t|r|b|l|x|y}-{size}

If we want to see all available sizes we can easily check them in the official Tailwind CSS documentation. It is worth mentioning that defining padding for an element is done in the same way, they differ only in the name, but the letter defining the side of the box model or sizes remain the same.

If we would like to use a specific value that Tailwind CSS does not offer, we do not necessarily have to modify it and write classes manually. If we put the size in square brackets we can use any valid CSS value and Tailwind CSS will read the class correctly and generate it for us:

<div class="ml-[15px] mr-[27px]">
  Custom left and right margins in TailwindCSS
</div>

Short HTML code with classes using sizes that Tailwind CSS does not offer.

 

For such HTML code, classes are created that define `margin-left: 15px` and `margin-right: 27px`. This is obviously not a feature you should use very often. It is a much better idea to modify the available sizes or add your own. However, if we have single cases where we need to use non-standard sizes we have an easy workaround to add them.

Responsiveness

Writing responsive websites has become a standard for today's web development. The share of mobile devices as recipients of websites has become too large to ignore. Tailwind CSS, in a very simple way, allows us to write pages responsively. Each class that we have in Tailwind we can write with a prefix defining the size from which it will work. Prefixes and corresponding media queries look like this by default in Tailwind CSS:

Breakpoint prefix

Minimum width

CSS

sm640px@media (min-width: 640px) { ... }
md768px@media (min-width: 768px) { ... }
lg1024px@media (min-width: 1024px) { ... }
xl1280px@media (min-width: 1280px) { ... }
2xl1536px@media (min-width: 1536px) { ... }

A table of available prefixes, corresponding widths, and media queries.


Suppose we want our card from the earlier example to update its width so that it varies between device sizes:

responsive card 3 4d573995af

A card component that occupies a different percentage of the available width depending on the width of the device on which the page is displayed.

 

To achieve this, we just need to add appropriate width control classes that will work only for specific sizes:

<section class="rounded-md border border-neutral-500 bg-neutral-700 hover:bg-neutral-600 transition-colors text-neutral-100 flex flex-row items-start cursor-pointer sm:w-5/6 md:w-4/6 lg:w-3/6">
  <img src="http://placekitten.com/100/100" alt="cat" class="py-4 pl-4 aspect-square" />
  <p class="mx-4 my-3 leading-4">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat.
  </p>
</section>

Adding class `sm:w-5/4` makes that for devices with width from `640px` the component will occupy 83.3% of the available width, for devices with width from `768px` it will be 66% and for `1024px` only 50%.

 

Dark mode

The dark mode has become an increasingly common request as some users prefer it to a light-colored look of websites. For some people it is simply more pleasant in perception, others think that it is less glaring in the eyes when browsing the Internet late at night.

In Tailwind CSS, the dark mode handling is done similarly to responsiveness handling. We just need to add the prefix `dark` to the class name and our class will work only if the page will be launched in the dark mode. Happily, dark mode detection is a feature that many browsers support natively. When we set the dark mode on the operating system level, the website will know about it and will display the appropriate mode. However, if we need to switch between these modes manually, we can change the behavior of the Tailwind CSS. By defining `darkMode` as a `class` in the `tailwind.config.js` file, classes with the `dark` prefix will only work if there is a `dark` class on the element above them.

module.exports = {
  darkMode: "class",
  // ...
}

Switching the automatic dark mode detection to manual.

 

Let's take a simple HTML example of how we can show and hide content depending on the dark mode when it’s configured as `class`:

    <main class="dark">
      <h3 class="dark:hidden">Light mode</h3>
      <h3 class="hidden dark:block">Dark mode</h3>
    </main>

Example of HTML code where we have 2 `<h3>` headers with different content. Since above we have an element with the class `dark` we will display a header with the content "dark mode". If we remove it and nowhere in the DOM hierarchy upwards there is an element with class `dark` – the user will see the header with the "Light mode" content.
 

Tailwind extensibility

In the `tailwind.config.js` file we can notice the `theme` and `plugin` fields. They are used to upload additional capabilities to Tailwind CSS and to configure it for our needs. Using the `theme` property, we can add an extension, e.g. a new color, or spacing, and Tailwind CSS will generate classes for us that will be written in the same way as its built-in ones. We can also override values if their original values do not fit our needs.

module.exports = {
  content: ["./src/**/*.html"],
  theme: {
    fontFamily: {
      sans: ["Graphik", "sans-serif"],
    },
    extend: {
      colors: {
        midnight: "#121063",
      },
    },
  },
  plugins: [],
};

An example of the `tailwind.config.js` file where we changed the default sans `fontFamiliy` in the theme and extended it with an additional color named `midnight`.

 

The plugins add an extra set of classes, worth mentioning here are the official plugins typography and forms. The first one adds a couple of classes to display the content as Markdown text. It is useful when we need to display HTML with semantic tags that we do not have access to, so we cannot add our classes to it. This often happens when we need to display content from the CMS. The second one is simply responsible for styling the forms; by default it styles all the elements like `input`, `textarea`, or `select` using the tag selectors. We can choose the option where we have to assign the `form-input` classes manually to apply the styles.

module.exports = {
  content: ["./src/**/*.{html,js}"],
  theme: {
    extend: {},
  },
  plugins: [
    require('@tailwindcss/typography'),
    require("@tailwindcss/forms")({
      strategy: 'class',
    }),
  ],
};

Tailwind CSS configuration with typography plugin and forms. By configuring the forms plugin strategy we have to manually assign which form fields will be styled.

 

Editor support

Tailwind CSS has one more fantastic feature in store besides a tool to build a CSS file. If our tool in the daily work is Visual Studio Code, we have an official plugin for it. Thanks to it, in HTML and CSS files we have classes autosuggestion and an available list of values for them. We can also see the used color prepended to the class name, and when we hover the mouse over one of the classes we have a preview of the actual CSS code that is defined by it.

tailwind intellisense 8d6ba26e69

Showing the class names autosuggestions when editing the HTML file. When we hover over a class we can see what CSS code it contains.

 

It is worth mentioning that if we extended or changed the configuration of Tailwind with the `tailwind.config.js` file our changes will also be taken into account in Visual Studio Code. The suggestions and generated CSS code work even for custom colors, spacing, etc. that we defined.

If we prefer to use the IDE from JetBrains, there is a plugin available for them, too, offering similar facilities.

 

Prototyping

If you don't want to play around with configuring a project to use Tailwind CSS, there is a way you can easily put it on our site. You just need to embed the script from CDN:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script src="https://cdn.tailwindcss.com"></script>
  </head>
  <body class="bg-neutral-800">
    <main class="content p-10 bg-neutral-200 bg-opacity-5 text-neutral-200">
      <h3 class="text-3xl font-bold leading-tight my-4">
        Look, I can use tailwind on the fly, without any build steps!
      </h3>
    </main>
  </body>
</html>

After adding one JavaScript file to the page, we can use Tailwind CSS classes in HTML.

It is worth mentioning that using Tailwind CSS in such a way is not suitable as a production solution. It is only a simple and easy way to check how we are working with it.

Now you know how to use Tailwind CSS in your projects

I hope you could find out how powerful and flexible Tailwind CSS can be. It offers us a rich collection of CSS classes and allows us to easily create responsive websites with support for the ever-popular dark mode. Thanks to this, our pages meet today's requirements while offering a reasonable size of uploaded CSS files.

Classes in Tailwind CSS were written with modern browsers and their capabilities in mind. To make working with it enjoyable, the authors needed to make some brave decisions, namely the lack of support for older browsers. We should always remember to choose the technology responsibly and thoughtfully based on our requirements.

There are a lot of classes that Tailwind CSS offers and, despite great documentation, the beginnings may seem difficult because of the constant switching between it and the editor. Fortunately, with help comes a plugin that offers class name suggestions and a preview of their values. It is a tool that makes the beginnings easier, but it is also indispensable in everyday work – even for those software developers who already have some experience with Tailwind CSS.

Very often, programmers have a problem with how to choose a good name for a variable, class, or function; the same applies to writing CSS. Luckily, Tailwind CSS eliminates this problem because we get a ready-made set of named classes with full documentation. Each name defines both attribute and value, and optionally also breakpoint and dark or light mode operation. This takes away the naming problem and makes using Tailwind CSS faster over time by remembering what classes we have and what they are for.

If we have comments or suggestions regarding the built-in styles that Tailwind CSS offers, we can customize them to our needs very easily. Not only can we add new values, but we can also change the default values for breakpoints, text sizes, and fonts.

In short, Tailwind CSS is a fantastic tool for starting new projects and has been designed in a way that makes it scale well with the growth of the application. All in all, it’s definitely worth learning Tailwind CSS, using it in your projects and building captivating website designs with it.

And what are your experiences with utilizing Tailwind CSS classes? Do you find this framework useful? To you, what are its advantages over other CSS frameworks? And do you think Tailwind CSS is worth mastering?

Rated: 4.8 / 12 opinions
Bartosz Szewczyk 362d896fa9

Bartosz Szewczyk

Frontend developer at Codete with a passion for simple solutions to non-trivial problems. Lover of improving work tools and reading other people's code. In his free time, he’s a runner and tap dancer. He also enjoys creating simple 2D games using the Unity engine.

Our mission is to accelerate your growth through technology

Contact us

Codete Global
Spółka z ograniczoną odpowiedzialnością

Na Zjeździe 11
30-527 Kraków

NIP (VAT-ID): PL6762460401
REGON: 122745429
KRS: 0000983688

Get in Touch
  • icon facebook
  • icon linkedin
  • icon instagram
  • icon youtube
Offices
  • Kraków

    Na Zjeździe 11
    30-527 Kraków
    Poland

  • Lublin

    Wojciechowska 7E
    20-704 Lublin
    Poland

  • Berlin

    Bouchéstraße 12
    12435 Berlin
    Germany