Styling with TailwindCSS and DaisyUI
Learning objectives
- You know the basics of styling applications using TailwindCSS and DaisyUI.
TailwindCSS provides a set of utility classes for styling the application. DaisyUI on the other hand simplifies the usage of TailwindCSS by providing a streamlined set of components that are built with TailwindCSS. Let's look into styling with them.
Common parts
Most applications feature a navigation bar and a footer. These are common parts of the application that are shared across the pages -- thus, it is meaningful to implement them as a part of the layout. As a starting point, we have the following contents in +layout.svelte
:
<script>
import "../app.css";
</script>
<header>
<h1>My application</h1>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/contact">Contact</a>
</nav>
</header>
<div>
<slot />
</div>
<footer>
<p>My application is cool.</p>
</footer>
DaisyUI comes with a set of guides that can be used to create a navigation bar and a footer into the page. Let's first add the navigation bar.
To do this, let's create a new Svelte component called Navbar.svelte
into the src/components
folder. Copy the following contents to the file -- the following is a modified version of the existing header element from the +layout.svelte
that utilizes a navbar example from DaisyUI documentation.
<header class="navbar bg-base-100">
<div class="flex-1 text-xl">My application</div>
<nav class="flex-none">
<ul class="menu menu-horizontal px-1">
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>
</header>
Now, modify the +layout.svelte
file to import the new Navbar.svelte
component and replace the old header
element with the component. After the change, the +layout.svelte
should look as follows.
<script>
import "../app.css";
import Navbar from "../components/Navbar.svelte";
</script>
<Navbar />
<slot />
<footer>
<p>My application is cool.</p>
</footer>
Now, let's add the footer. Create a new Svelte component called Footer.svelte
into the src/components
folder. Copy the following contents to the file -- the following utilizes directly one of the existing footer examples from DaisyUI documentation, replacing only the text.
<footer class="footer footer-center p-4 bg-base-300 text-base-content">
<aside>
<p>My application is cool.</p>
</aside>
</footer>
Now that the footer component has been created, import it to the +layout.svelte
and replace the old footer
element with the component. After the change, the +layout.svelte
should look as follows.
<script>
import "../app.css";
import Navbar from "../components/Navbar.svelte";
import Footer from "../components/Footer.svelte";
</script>
<Navbar />
<slot />
<Footer />
Now, the application looks as follows.

Presently, it is not clear that the navigation bar is separate from the body text, as there are no visual separators. TailwindCSS comes with a handful of utility classes that are useful here -- let's use drop shadow to add a shadow to the navigation bar. In effect, we add the class drop-shadow
to the navbar
element. Modify the Navbar.svelte
file to match the following.
<header class="navbar bg-base-100 drop-shadow">
<div class="flex-1 text-xl">My application</div>
<nav class="flex-none">
<ul class="menu menu-horizontal px-1">
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>
</header>
Now, when the application is reloaded, the navigation bar has a shadow.

Next, we'll look into adjusting the individual pages. Befor that, modify the +layout.svelte
further to add a main
element to the page, which contains the slot
element. The main
element is used to indicate the location of the main content of the specific page. Furthermore, use the classes container mx-auto
for styling the main element. This way, the content of the page is centered and has a maximum width. After the change, the +layout.svelte
should look as follows.
<script>
import "../app.css";
import Navbar from "../components/Navbar.svelte";
import Footer from "../components/Footer.svelte";
</script>
<Navbar />
<main class="container mx-auto">
<slot />
</main>
<Footer />
Main page
The main page of the application is the page that is shown when the user first opens the application. A caricature of a main page -- or the home page -- often contains a navigation bar, a hero section, a few cards and a footer. From these, the navigation bar and the footer are already in the layout, while the hero and the cards would be specific to the main page.
For the hero element, we can use DaisyUI's Hero component. Create a new component called Hero.svelte
and place it to the src/components
folder. Copy the following contents to the file -- as you might guess, it is a modified version of an existing hero example from DaisyUI documentation.
<div class="hero min-h-screen bg-base-200">
<div class="hero-content text-center">
<div class="max-w-md">
<h1 class="text-5xl font-bold">Hello world!</h1>
<p class="py-6">Scroll down and pick your journey.</p>
</div>
</div>
</div>
Next, import the Hero component to the +page.svelte
in the src/routes
folder, replacing the existing content with the Hero component. After the change, content should be as follows.
<script>
import Hero from "../components/Hero.svelte";
</script>
<svelte:head>
<title>My application</title>
</svelte:head>
<Hero />
Next, we'll create a card component. As the application has little content beyond the pages, we'll use the card component to link to those pages. For the card component, we can utilize the existing card functionality as the basis.
Create a component called Card.svelte
and place it to the folder src/components
. We'll use multiple cards, so we wish to give the card properties. To do this, we'll use the $props()
function we've also used in the past. Copy the following content to the Card.svelte
.
<script>
let { title, description, link } = $props();
</script>
<div class="card w-96 bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title">{title}</h2>
<p>{description}</p>
<div class="card-actions justify-end">
<a href="{link}" class="btn btn-primary">Go!</a>
</div>
</div>
</div>
Now, modify the +page.svelte
in the src/routes
folder to import the Card.svelte
component and use it to create a few cards -- each card links the user to a specific page. After the change, the +page.svelte
should look as follows.
<script>
import Hero from "../components/Hero.svelte";
import Card from "../components/Card.svelte";
</script>
<svelte:head>
<title>My application</title>
</svelte:head>
<Hero />
<Card title="Home" description="You are here." link="/" />
<Card title="About" description="About.. what?" link="/about" />
<Card title="Contact" description="Get in touch" link="/contact" />
When you open up the page, you'll notice that the cards are stacked on top of each other. This is a good place for the flex layout that we learned about when working with Cascading Style Sheets.
With TailwindCSS, we can use the flex utility classes to create a flex layout. To do this, we'll create a new div
element and place the cards inside to the div
element. We further add the flex
class to the div
element, highlighting that the contents should be laid out using the flex layout. In addition, we add the justify-evenly
class to the div
to indicate that the flex items should be evenly distributed along the main axis. After the change, the +page.svelte
should look as follows.
<script>
import Hero from "../components/Hero.svelte";
import Card from "../components/Card.svelte";
</script>
<svelte:head>
<title>My application</title>
</svelte:head>
<Hero />
<div class="flex justify-evenly">
<Card title="Home" description="You are here." link="/" />
<Card title="About" description="About.. what?" link="/about" />
<Card title="Contact" description="Get in touch" link="/contact" />
</div>
As you notice, there is no margin or padding between the cards and the Hero element. To add margin, we use the margin utility classes, which provide shorthands for adding margin to the top mt-
and margin to the bottom mb-
. Below, the div
for the cards uses mt-10
and mb-10
, which corresponds to adding 40 pixels of margin to the top and to the bottom of the area.
<script>
import Hero from "../components/Hero.svelte";
import Card from "../components/Card.svelte";
</script>
<svelte:head>
<title>My application</title>
</svelte:head>
<Hero />
<div class="flex justify-evenly mt-10 mb-10">
<Card title="Home" description="You are here." link="/" />
<Card title="About" description="About.. what?" link="/about" />
<Card title="Contact" description="Get in touch" link="/contact" />
</div>
But.. It looks horrible?
Even with our styling, the site does not look great. The site is styled, however -- it is a start that one could build on top of.
Other pages
The other pages of the application are the about page and the contact page. For styling them, a good starting point would be considering what the key contents should be, and to explore the DaisyUI components to find a suitable component for the purpose.
If no corresponding component is found, it is possible to also build the component from scratch using TailwindCSS.
To see some examples of the possibilities, check out the TailwindCSS showcase page. Note, however, that many of the highlighted sites have been built with the help of designers with plenty of practice from designing web sites.