Black Friday: coupon FRIDAY24 for 40% off Yearly/Lifetime membership! Read more here
Courses

Tailwind CSS for Laravel Developers

Start with Tailwind: Laravel Breeze Example

The best way to start with Tailwind in Laravel is to install the Laravel Breeze starter kit, which automatically installs and configures Tailwind for you.

When you land on the Login page, you see an excellent design:

If we take a look at the Blade code, we may see this:

<!-- Email Address -->
<div>
<x-input-label for="email" :value="__('Email')" />
<x-text-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autofocus autocomplete="username" />
<x-input-error :messages="$errors->get('email')" class="mt-2" />
</div>
 
<!-- Password -->
<div class="mt-4">
<x-input-label for="password" :value="__('Password')" />

Yes, it uses Blade components, but I want you to pay attention to CSS classes:

  • x-text-input class="mt-1"
  • x-input-error class="mt-2"
  • div class="mt-4"

See that ' mt-X`? That is a Tailwind class; "mt" stands for "Margin Top".

And yes, the bigger the number, the larger the margin.

For example, if we change the x-text-input class="mt-4", the visual result will be this:

That is how you describe the classes for your HTML elements in Tailwind: combining many small classes defining the looks and positioning of a component or HTML element, to put it short.

At first, it may look confusing and even "ugly", especially if you come from a Bootstrap background. You may think: "What, I need to write 5-10 classes instead of just something like div class="card""? It feels almost like inline CSS.

But the main counterargument is what we did in the example above. We quickly changed the margin from mt-1 to mt-4. For that, we didn't need to create a separate CSS class like "input-with-bigger-margin" or add an extra inline style like <div class="input" style="...".

That's precisely the central philosophy of Tailwind: by combining small "utility" classes into how an element should look, you can quickly change that look. And when you get used to it, with more practice, you start thinking in those utility classes, remembering their names and behavior, and it starts feeling very natural.


Other Possible mt-X Numbers?

In almost every browser, 16px is the standard for proportional fonts. And there's a good reason: this size is easy to scale. So the base font size would be 1rem = 16px.

In TailwindCSS, those numbers are quarters of base rem size. Let's look at the mt-9 class. That would result in 9 quarters of 1rem: 1 / 4 * 9 = 2.25rem. The mt-9 class would apply the margin-top: 2.25rem style, which is 36px (16px * 2.25) if the base font size is 16px.

The same numbering logic applies to all class names, including, but not limited to, margins and paddings. It may look like you can put any number there, but that is untrue. For precise available classes, please look up the TailwindCSS documentation.


Troubleshooting

Wait, Why mt-8 Doesn't Work?

Ok, let's try to change the same Breeze example from mt-1 to mt-8:

<x-text-input class="mt-8" ... />

But if we refresh the page, it won't work. The margin would disappear at all.

Why?

Here, you need to understand how Tailwind classes are compiled.

When using TailwindCSS, your project's app.css file is compiled with the classes only in use.

First, install node dependencies defined in your package.json file using this command:

npm install

Then, compile new files using this command.

npm run dev

The dev part in the command will start Vite with a hot-reload feature, and changes will immediately affect when you add or remove TailwindCSS classes. This command is useful when developing your application in the local environment.

To compile static files, use build instead of dev.

npm run build

Compiling your CSS files has the advantage of smaller file sizes, and that affects your page loading time.

Compiled CSS file takes up 30.82 kB on disk. The server transfers it with compressions, which would take only 6 kB.

public/build/assets/app-9c5f9671.css 30.82 kB │ gzip: 6.00 kB

In comparison, Bootstrap takes up 232.95 kB on disk and 34.24 kB to transfer. That is more than seven times on disk, which is not the issue, but five times more data is transmitted via a network, which may seem trivial at first but could impact users with slower internet connections.

Optionally, you can include all TailwindCSS classes via CDN by adding this script into your <head> part of the page to play around without compiling CSS files, but it should not be used in production so that we won't discuss sizes on this one.

<script src="https://cdn.tailwindcss.com"></script>

I compiled a CSS file, but classes still won't apply. What should I do?

That often happens when you have Blade, Vue, or JS files in the location where TailwindCSS doesn't look for class names in use.

Check the TailwindCSS config in your project root directory and add paths to the content array.

tailwind.config.js

// ...
 
export default {
content: [
'./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',
'./storage/framework/views/*.php',
'./resources/views/**/*.blade.php',
],
// ...

Double asterisk ** means to look into all subdirectories.

My file is in the path and has the correct extension, but some classes still won't apply; what now?

You're likely constructing your class names dynamically. That is especially very common if you're using frameworks like Vue or React on top.

Don't do that:

<div class="text-{{ error ? 'red' : 'green' }}-600"></div>

Instead, use full class names.

<div class="{{ error ? 'text-red-600' : 'text-green-600' }}"></div>

How can I always have some classes to be available?

If, for some reason, you need classes present in your compiled file at all times, you have to safelist them. That can be done by adding the safelist key with an array of class names into your TailwindCSS configuration.

tailwind.config.js

// ...
 
export default {
content: [
'./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',
'./storage/framework/views/*.php',
'./resources/views/**/*.blade.php',
],
 
safelist: [
'bg-red-600',
'text-3xl',
'lg:text-4xl',
],
// ...

Safelisting is a last resort and should only be used when scanning certain content for class names is impossible.

More information on safelisting classes.

avatar

Just in time. I'm about to start with tailwind. Povilas, would you recommend any UI kit for it (I'm going to pair it with VUE)?

avatar

I don't think these are related questions. UI is about CSS mostly, in my opinion, and then you add your custom Vue on top.

I personally use the official Tailwind UI, but it's a personal preference, we mentioned other popular kits at the end of the course, in the last lesson.

avatar

Thanks for the answer.

avatar

@jakub , you can try https://daisyui.com/

avatar

Hey Povilas Korop Great content can you start course Paypal and Stripe integration in laravel (blade)

avatar

Since I started using Paddle, it solved my personal problems cause it supports both cards and PayPal under the hood, especially combined with Laravel Spark.

So I don't think there's a need to create separate courses on PayPal and Stripe anymore.

For Stripe, actually, Laravel Cashier documentation is great, and it got even better now - see Taylor's tweet.