List

Tailwind CSS: It looks awful, and it works

Tailwind CSS: It looks awful, and it works

by Adam Wathan

In his talk at Rails World 2023, Adam Wathan, the creator of Tailwind CSS, presents an argument for the practicality of using utility-first CSS frameworks like Tailwind in web development. He challenges the conventional wisdom around the "separation of concerns" in HTML and CSS, suggesting instead that presentational class names make code far easier to maintain.

Key points discussed in the talk include:
- Common Misconception: Many developers feel that using numerous utility classes within HTML looks cluttered and confusing. However, Adam emphasizes that actual experience with Tailwind often leads to a change in mindset, revealing the benefits of this approach.
- Live Coding Session: Adam engages the audience by building a testimonial card live, demonstrating Tailwind's capabilities. He scaffolded the necessary HTML structure while applying Tailwind classes in real time, illustrating how to create a card with a clean design efficiently using utility classes.
- Styling with Tailwind: Throughout the live coding session, Wathan highlights the simplicity and speed of styling elements directly in HTML using Tailwind's utility classes rather than writing complex CSS in external files. For example, he shows how to apply background colors, border radius, shadows, and responsive layouts using straightforward class names without needing to switch contexts.
- Handling Interactivity: He points out Tailwind's ability to manage conditional styles for interactive elements, such as hover states, using class prefixes, which inline styles cannot accomplish effectively.
- Avoiding Duplication: Addressing concerns about HTML duplication, Wathan suggests utilizing templating languages that allow for reusable components while keeping the styling intact. He also emphasizes creating partials in Rails for optimized markup management.
- Responsive Design: Adam showcases how to achieve responsive layouts effortlessly with Tailwind, where classes can change styles based on screen size, using the framework's grid utilities.
- Dark Mode & Customization: The talk also touches on Tailwind's handling of dark mode and allows developers to customize styles based on user preferences efficiently.

In conclusion, Adam Wathan underscores that Tailwind allows developers to create robust, maintainable designs with minimal context shifting and complexity, thereby advocating for its adoption in modern web development. He invites those unfamiliar with Tailwind CSS to consider trying it out, presenting it as a powerful tool to streamline their workflow and enhance productivity.

In his talk at #RailsWorld, Tailwind CSS creator @AdamWathan of @TailwindLabs will explain why “separation of concerns” isn’t the right way to think about the relationship between HTML and CSS, why presentational class names lead to code that’s so much easier to maintain, as well as loads of tips, tricks, and best practices for getting the most out of Tailwind CSS.

Links:
https://rubyonrails.org/
https://tailwindcss.com/

#RailsWorld #RubyonRails #Rails #railwindcss #tailwind #frontend

Rails World 2023

00:00:15.400 Good afternoon, everyone. I'm Adam, and I've been a huge admirer of all the work that's been done in the Rails community. All the ideas and innovations that have happened since the creation of the framework have inspired me throughout my entire career. So, it's really an honor to be here and to be a part of this. I'm really excited, so thank you so much for having me. I'm the creator of Tailwind CSS, and I'm here to tell you that it’s not as bad as it looks.
00:00:39.680 Let's get into it! So let's say we're going to build this little testimonial card example, and we want to style it with a more traditional CSS approach. We might write some HTML that looks something like this. This is kind of what the final thing would look like—pretty clean. If we wanted to do the same thing with Tailwind, the HTML would look something like this.
00:01:03.399 Now, if there's anything that I've sort of learned over the last six years or so of maintaining and building Tailwind CSS, it's that there are literally no words I could say that would convince you that littering your HTML with dozens of presentational classes is actually a good idea. There’s no way to look at that and think it's good if you haven’t used Tailwind.
00:01:22.799 That said, what I find is that most people, when they actually give it a try, start to feel, very quickly, like, how did I ever think writing this was a better idea? So instead of trying to convince you that this is a valid way to do things, I think the best approach is just to build some things together and let you experience it yourself. At the same time, I’ll share some useful tips, tricks, and best practices about how to get the most out of using Tailwind in a Rails app.
00:02:00.960 The whole talk from this point on is going to be live coding, so please pray for me. I have over here in Figma a beautifully designed profile card that I want to try and recreate with Tailwind. The first thing I generally do is scaffold out all the markup that I think I will need to get all these pieces in place. We need some sort of element to hold the whole card, an image at the top for the background, and then a group of items below including an avatar, name, title, and link. I will create another wrapper for that.
00:02:44.239 Next, I'll drop in an image tag for the profile photo, add a P tag for the name, and then for the title and link, we’ll throw that into a div since it’s an inline element. We have the name 'Eric Lane', a title of 'Project Manager', and a link to her LinkedIn profile. For the images, I've just got them sitting in my project. Forgive my rookie use of ERB syntax, but for the header, I think it was 'header-ocean.jpeg' and for the profile photo, I believe it's 'profile-eric-lane.jpg'. Let’s see what we’ve got.
00:03:32.519 Now, let's style it. Where would I start? The card should be white with a border radius and a shadow. We can do all that with just classes right in our HTML. We'll start with 'bg-white' to make the card white, and for the border radius, my good friend Steve suggested a 16 pixel corner radius. Using the IntelliSense extension for auto-complete, we find that 16 pixels is represented by 'rounded-2xl'. Now let’s slap a shadow on there.
00:04:06.280 You can't really see the shadow due to some overflow happening, so let's add 'overflow-hidden' to ensure that the corners of the image don't peek out. Now you can see the whole element has smooth, rounded corners. Next, we want to style the header image. It is inset from the edge of the card by 4 pixels. To accomplish that, we'll wrap the whole thing in another element and apply some padding to it.
00:04:50.280 With 'p-1', we get that extra padding of four pixels, which should bring us closer. Now that we've wrapped the image, we can see we have those square corners. So, Steve cleverly adjusted the corner radius of the image to match the outer corner radius of the card, which is 12 pixels (16 minus 4). Thus, we need to set 'rounded-xl' for that image.
00:05:38.400 Next, we want to apply padding only to the top and sides of the card since the image doesn't fill the whole card. Hence, we will remove padding from the bottom using 'pb-0'. The header image has a height of 128 pixels. Tailwind allows us to easily manage heights just like we can with 'h-32', using its predefined spacing scale which operates on a four-pixel base. Now, we set 'w-full' to ensure the image fills the entire width of the card.
00:07:20.680 However, this may stretch the image, so we can utilize the 'object-cover' utility to maintain the image's aspect ratio. Next, we will create the bottom half of the card, making the avatar round and setting its size to 80 pixels. Using 'rounded-full' will accomplish this. Tailwind trains your math skills quite well! We will also inset everything from the edge of the card by 24 pixels.
00:08:51.680 To apply padding here, we’ll use 'p-6' for uniform padding on all sides. We’ll remove the top padding since we already accounted for that so that everything looks snug. Now, we style the text. The text uses the default size of 16 pixels, so we can set 'font-semibold' to modify the font style. For the subtitle, we will use 'text-sm' and a softer gray color, like 'text-gray-600'. Below that will be a link styled with a small font.
00:10:42.000 We can style the link with an indigo color, setting the base font size on the parent element to ensure proper scaling. If any spacing is missing between these elements, we can use 'mt-4' to create some room. Additionally, let's increase the weight of the link font using 'font-medium' and apply a bit more margin. We also need to negate the margin around the image to create a smoother overlap effect.
00:12:24.320 To achieve that, we can use CSS outline properties to create a notch around the image without resorting to complex custom CSS. Now we have totally recreated our design using only Tailwind without diving into any CSS files, showcasing the power of this CSS framework.
00:13:07.120 You may be thinking, 'But I could have done all of this with inline styles!' Well, there are a couple of things you can't do with inline styles, such as applying hover styles. In Tailwind, we can apply styles conditionally by prefixing classes with a state. Using 'hover:text-indigo-900', we can quickly change styles based on user interaction.
00:13:37.480 You can also customize focus styles, replacing the default ring with an underline just by using Tailwind’s utility classes. Here’s a basic example demonstrating how to build something like a widget with Tailwind.
00:14:49.680 Now, what if you want to change styles across multiple elements? For example, hovering over a card could trigger changes in other elements. Tailwind provides neat abstractions that allow you to assign a group and use 'group-hover' to create linked interactions. Adding transition utilities will smooth the animations, achieving a dynamic user experience without needing multiple lines of complex CSS.
00:15:52.720 At this point, a common concern arises: how do I manage duplication in my HTML? It’s true that there are a lot of tiny details that might clutter your markup, especially if you're reusing components. Let’s say we create duplicate cards; this could lead to messy HTML. However, the great news is that templating languages were designed to optimize this problem.
00:17:09.240 You can simply render a loop for these cards, writing the markup once, while all the styles maintain their integrity, thus eliminating duplication. If you want to modify an image's or card's shape, you simply do it in one place. For more extensive reuse, we can create partials in Rails, enabling us to use the component anytime, anywhere.
00:18:26.720 Templating offers a great benefit, but there are occasions when creating partials feels excessive. In frameworks like React or Vue, creating components for every little thing in a page is common. In my experience with ERB or Blade templates, it’s often unnecessary to create a partial for something trivial, like a single link.
00:19:39.840 Let’s consider a case where we want to style a link used multiple places in a project. Instead of creating a partial, I’d grab all the styles applied to that link, create a new class in a CSS file, and utilize Tailwind’s 'apply' helper to extract those styles into a custom class. Though customizable, I advise caution; it’s best for simple, single-element things, not for complex components.
00:21:43.720 Let’s explore another demo, showcasing a layout that resembles an Airbnb interface, demonstrating responsive design with Tailwind. The layout adapts from a single column to multiple columns based on screen size, utilizing the gaps provided by CSS grid, removing margin management from the equation.
00:23:40.600 To achieve responsive layouts using Tailwind, we can change grid layouts based on breakpoints. For instance, at medium screens and above, we can switch this layout to a two-column grid. Exploring this further, we can create a mosaic layout by utilizing 'md:col-span-2' or similar utilities to adjust the element's span based on screen size.
00:25:12.760 When dealing with dark mode support, we can apply prefixing to style elements based on current modes. In Tailwind, you specify styles for dark mode directly, rather than allowing the library to magically decide for you. This grants you more control, enabling sophisticated designs such as gradient effects or variable text colors based on user preferences.
00:26:32.000 Here's a practical example: we want to create a customizable button color for a payment form, allowing end users to set their brand colors. While inline styles could manage basic colors, Tailwind excels at enabling actionable hover states, which require JavaScript data attributes.
00:28:58.640 In this demo, we managed to apply CSS variables for both button background and text colors while retaining hover styles through Tailwind’s utility features. Hopefully, those of you already using Tailwind picked up a few interesting tricks and those who haven’t yet might consider giving it a shot. It’s remarkable what can be done simply in HTML, minimizing context switches. My experience shows that managing Tailwind classes in HTML is usually much easier than maintaining traditional CSS.
00:30:11.720 Thank you for checking this out. If you want to talk more about Tailwind, feel free to find me after the talk!