Tailwind CSS Text Decoration
Text decoration refers to CSS properties that define how text is enhanced beyond its basic typographic rendering. It allows developers to add underline, overline, line-through, or no underline to the texts.
Tailwind CSS offers predefined classes to make working with text decoration properties seamless and efficient. By leveraging Tailwind's built-in text decoration utilities, you can easily enhance the presentation of text while maintaining the flexibility to conditionally style elements based on user interaction, responsive breakpoints, or specific states.
Class | Properties | Example |
---|---|---|
underline | text-decoration-line: underline; | <div className="underline"></div> |
overline | text-decoration-line: overline; | <div className="overline"></div> |
line-through | text-decoration-line: line-through; | <div className="line-through"></div> |
no-underline | text-decoration-line: none; | <div className="no-underline"></div> |
Overview of Text Decoration
Underline
The utility underline
adds underlining to the text of the <p>
tag. In traditional CSS, this equivalent style would be manually written as: text-decoration-line: underline;
export default function AboutKombai() { return ( <p className="underline p-4"> Kombai for Web is an ensemble of deep learning and heuristics models trained to understand designs like humans. Developers can prompt Kombai with design files in their Figma and get high-quality React and HTML + CSS code in just one click per component. </p> ); }
Overline
The utility overline
adds overlining to the text of the <p>
tag. In traditional CSS, this equivalent style would be manually written as: text-decoration-line: overline;
export default function AboutKombai() { return ( <p className="overline p-4"> Kombai for Web is an ensemble of deep learning and heuristics models trained to understand designs like humans. Developers can prompt Kombai with design files in their Figma and get high-quality React and HTML + CSS code in just one click per component. </p> ); }
Line Through
The utility line-through
adds line-through to the text of the <p>
tag. In traditional CSS, this equivalent style would be manually written as: text-decoration-line: line-through;
export default function AboutKombai() { return ( <p className="line-through p-4"> Kombai for Web is an ensemble of deep learning and heuristics models trained to understand designs like humans. Developers can prompt Kombai with design files in their Figma and get high-quality React and HTML + CSS code in just one click per component. </p> ); }
No Underline
The utility no-underline
removes underlining from the text of the <p>
tag. In traditional CSS, this equivalent style would be manually written as: text-decoration-line: none;
export default function AboutKombai() { return ( <p className="no-underline p-4"> Kombai for Web is an ensemble of deep learning and heuristics models trained to understand designs like humans. Developers can prompt Kombai with design files in their Figma and get high-quality React and HTML + CSS code in just one click per component. </p> ); }
States and Responsiveness
Tailwind CSS can also add utilities dynamically based on user interaction, viewport size, or custom conditions.
Hover and Focus States
Pseudo-classes like hover
, focus
, or active
are used for utility-driven styling.
export default function HoverLink() { return ( <> <p className="font-bold p-4 text-red-600"> Hover the below text to remove underline 👇 </p> <p className="underline hover:no-underline p-4"> Kombai for Web is an ensemble of deep learning and heuristics models trained to understand designs like humans. Developers can prompt Kombai with design files in their Figma and get high-quality React and HTML + CSS code in just one click per component. </p> </> ); }
- Initially, the anchor text appears underlined due to the
underline
utility. - On hover,
hover:no-underline
removes the underline.
Breakpoint Modifiers
Tailwind’s breakpoint prefixes like sm:
, md:
, lg:
enable you to conditionally style elements for specific screen sizes.
export default function ResponsiveText() { return ( <> <p className="font-bold p-4 text-red-600"> The below text is underlined only on 640px screens or above 👇 </p> <p className="no-underline sm:underline p-4"> Kombai for Web is an ensemble of deep learning and heuristics models trained to understand designs like humans. Developers can prompt Kombai with design files in their Figma and get high-quality React and HTML + CSS code in just one click per component. </p></> ); }
- On mobile phones (i.e., screens smaller than 640px), the
no-underline
utility is applied. - On tablets, laptops, and large monitors (screens 640px and larger, represented by sm), the
underline
utility gets activated.
Since, Tailwind has a breakpoint system that is mobile-first, prefixes like sm
use min-width
instead of max-width
. So, the utilities are applied on the breakpoint of the prefix and above.
Go to the browser developer tools and check the above code on a breakpoint above 640px, the underline will be added.
Real World Examples
Product Feature List with Underline Hover Effects
This component showcases a product feature list where each item has a underline animation on hover.
export default function ProductFeatures() { const features = [ { title: "Cloud Storage", description: "Secure and scalable storage solution", icon: "https://images.unsplash.com/photo-1590859808308-3d2d9c515b1a?w=500", alt: "Cloud storage icon" }, { title: "Real-time Analytics", description: "Advanced data visualization tools", icon: "https://images.unsplash.com/photo-1551288049-bebda4e38f71?w=500", alt: "Analytics dashboard" }, { title: "Team Collaboration", description: "Seamless workflow integration", icon: "https://images.unsplash.com/photo-1522071820081-009f0129c71c?w=500", alt: "Team collaboration" } ]; return ( <div className="max-w-4xl mx-auto p-8"> <h2 className="text-3xl font-bold mb-8">Enterprise Features</h2> <div className="grid grid-cols-1 md:grid-cols-3 gap-8"> {features.map((feature, index) => ( <div key={index} className="group"> <img src={feature.icon} alt={feature.alt} className="w-16 h-16 rounded-lg mb-4" /> <h3 className="text-xl font-semibold group-hover:text-blue-600 decoration-blue-500 group-hover:underline decoration-2 underline-offset-4 transition-all duration-300"> {feature.title} </h3> <p className="text-gray-600 mt-2">{feature.description}</p> </div> ))} </div> </div> ); }
Article Preview Cards with Strikethrough Price
A component displaying article cards with strikethrough pricing for discounted items and hover on titles.
export default function ArticleCards() { const articles = [ { title: "Premium Photography Course", author: "Jane Cooper", image: "https://images.unsplash.com/photo-1452587925148-ce544e77e70d?w=800", alt: "DSLR camera on tripod", originalPrice: "$199", currentPrice: "$149", category: "Photography" }, { title: "Advanced Web Development", author: "John Smith", image: "https://images.unsplash.com/photo-1461749280684-dccba630e2f6?w=800", alt: "Coding on laptop", originalPrice: "$299", currentPrice: "$249", category: "Development" }, { title: "Digital Marketing Mastery", author: "Sarah Wilson", image: "https://images.unsplash.com/photo-1460925895917-afdab827c52f?w=800", alt: "Marketing analytics dashboard", originalPrice: "$159", currentPrice: "$99", category: "Marketing" } ]; return ( <div className="bg-gray-100 p-8"> <div className="max-w-6xl mx-auto grid grid-cols-1 md:grid-cols-3 gap-8"> {articles.map((article, index) => ( <div key={index} className="bg-white rounded-xl overflow-hidden shadow-lg"> <img src={article.image} alt={article.alt} className="w-full h-48 object-cover" /> <div className="p-6"> <span className="text-sm text-blue-600 font-medium"> {article.category} </span> <h3 className="text-xl font-bold mt-2 hover:underline decoration-gray-700 underline-offset-4"> {article.title} </h3> <p className="text-gray-600 mt-2">By {article.author}</p> <div className="mt-4 flex items-center gap-3"> <span className="text-gray-400 line-through decoration-red-500 decoration-2"> {article.originalPrice} </span> <span className="text-green-600 font-bold"> {article.currentPrice} </span> </div> </div> </div> ))} </div> </div> ); }
Navigation Menu with Double Underline Effect
A navigation menu component with a double underline effect on active items.
import { useState } from 'react'; const NavigationMenu = () => { const [activeItem, setActiveItem] = useState('Home'); const menuItems = [ { name: "Home", isActive: true }, { name: "Products", isActive: false }, { name: "Services", isActive: false }, { name: "About", isActive: false }, { name: "Contact", isActive: false } ]; return ( <nav className="bg-white border-b border-gray-200"> <div className="max-w-6xl mx-auto px-4"> <div className="flex justify-between items-center h-16"> <img src="https://images.unsplash.com/photo-1599305445671-ac291c95aaa9?w=200" alt="Company logo" className="h-8" /> <div className="flex space-x-1"> {menuItems.map((item) => ( <a key={item.name} href="#" onClick={(e) => { e.preventDefault(); setActiveItem(item.name); }} className={`text-gray-700 hover:text-gray-900 px-2 py-2 text-sm font-medium relative group ${ item.name === activeItem ? 'text-blue-600' : '' }`} > {item.name} {item.name === activeItem && ( <> <span className="absolute bottom-0 left-0 w-full h-0.5 bg-blue-600"></span> <span className="absolute bottom-2 left-0 w-full h-0.5 bg-blue-600"></span> </> )} <span className="absolute bottom-0 left-0 w-full h-0.5 bg-blue-600 scale-x-0 group-hover:scale-x-100 transition-transform duration-300"></span> </a> ))} </div> </div> </div> </nav> ); }; export default NavigationMenu;
Task List with Completion Strikethrough
A task management component that applies strikethrough decoration to completed items.
export default function TaskList() { const tasks = [ { id: 1, title: "Complete project proposal", completed: true, priority: "High", dueDate: "2023-12-01" }, { id: 2, title: "Review team presentations", completed: false, priority: "Medium", dueDate: "2023-12-03" }, { id: 3, title: "Update documentation", completed: true, priority: "Low", dueDate: "2023-12-05" }, { id: 4, title: "Client meeting preparation", completed: false, priority: "High", dueDate: "2023-12-02" } ]; return ( <div className="max-w-2xl mx-auto p-6 bg-white rounded-xl shadow-lg"> <h2 className="text-2xl font-bold mb-6">Task Manager</h2> <div className="space-y-4"> {tasks.map((task) => ( <div key={task.id} className="flex items-center justify-between p-4 bg-gray-50 rounded-lg hover:bg-gray-100 transition-colors duration-200" > <div className="flex items-center space-x-4"> <input type="checkbox" checked={task.completed} className="w-4 h-4 text-blue-600 rounded" readOnly /> <div> <h3 className={`font-medium ${ task.completed ? 'line-through decoration-gray-500 text-gray-500' : 'text-gray-900' }`}> {task.title} </h3> <p className="text-sm text-gray-500">Due: {task.dueDate}</p> </div> </div> <span className={`px-3 py-1 rounded-full text-sm font-medium ${ task.priority === 'High' ? 'bg-red-100 text-red-800' : task.priority === 'Medium' ? 'bg-yellow-100 text-yellow-800' : 'bg-green-100 text-green-800' }`}> {task.priority} </span> </div> ))} </div> </div> ); }
Event Schedule with Wavy Underline Highlights
An event schedule component featuring wavy underlines for special highlights.
export default function EventSchedule() { const events = [ { time: "09:00 AM", title: "Opening Keynote", speaker: "Emily Johnson", image: "https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=200", alt: "Emily Johnson profile", isHighlight: true, location: "Main Hall" }, { time: "10:30 AM", title: "Future of AI Panel", speaker: "David Chen", image: "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=200", alt: "David Chen profile", isHighlight: false, location: "Room 101" }, { time: "01:00 PM", title: "Networking Lunch", speaker: "Various Speakers", image: "https://images.unsplash.com/photo-1591115765373-5207764f72e7?w=200", alt: "Networking event", isHighlight: true, location: "Garden Area" } ]; return ( <div className="max-w-4xl mx-auto p-8 bg-gray-50"> <h2 className="text-3xl font-bold mb-8">Conference Schedule</h2> <div className="space-y-6"> {events.map((event, index) => ( <div key={index} className="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition-shadow duration-300"> <div className="flex items-center justify-between"> <div className="flex items-center space-x-4"> <img src={event.image} alt={event.alt} className="w-12 h-12 rounded-full" /> <div> <h3 className={`text-xl font-semibold ${ event.isHighlight ? 'decoration-yellow-400 decoration-wavy decoration-2 underline underline-offset-4' : '' }`}> {event.title} </h3> <p className="text-gray-600">{event.speaker}</p> </div> </div> <div className="text-right"> <span className="text-lg font-medium text-gray-800"> {event.time} </span> <p className="text-sm text-gray-500">{event.location}</p> </div> </div> </div> ))} </div> </div> ); }
Best Practices
Maintain Design Consistency
When creating cohesive designs, maintaining consistency in how text decoration styles are applied is essential. Tailwind CSS simplifies this by providing predefined classes, but it’s up to the designer to use them consistently.
Below is an example where navigation links share consistent underline styles on hover.
export default function NavigationMenu() { const links = [ { label: "Home", href: "/" }, { label: "Features", href: "/features" }, { label: "Pricing", href: "/pricing" }, { label: "About", href: "/about" }, ]; return ( <nav className="flex justify-between items-center p-5 bg-gray-100 w-96"> <div className="text-2xl font-bold text-blue-600">Kombai</div> <ul className="flex space-x-4 pl-4"> {links.map((link, index) => ( <li key={index}> <a href={link.href} className="text-gray-700 hover:text-blue-600 transition duration-300 underline decoration-transparent hover:decoration-blue-600 underline-offset-4 decoration-2" > {link.label} </a> </li> ))} </ul> </nav> ); }
- Use theme extensions to define custom
decoration-color
values for consistent branding. - Avoid mixing unrelated underline styles such as dotted on one element and solid on another unless it’s intentional for emphasis.
Leverage Utility Combinations
Combine utilities to create more dynamic and visually appealing interfaces. Tailwind’s design philosophy encourages thoughtful utility combinations. Use font sizes, colors, and decorations together to establish focus and hierarchy in your content.
export default function FeaturedArticle() { return ( <div className="max-w-2xl mx-auto p-6 bg-gray-50 rounded-lg shadow-sm h-screen"> <h2 className="text-3xl font-bold underline decoration-yellow-500 decoration-wavy underline-offset-4 mb-4"> Welcome to Kombai </h2> <p className="text-gray-700 text-sm leading-relaxed pt-4"> Kombai for Web is an ensemble of deep learning and heuristics models trained to understand designs like humans. Developers can prompt Kombai with design files in their Figma and get high-quality React and HTML + CSS code in just one click per component. </p> </div> ); }
Accessibility Considerations
Enhance Readability and Navigability
Text decoration utilities like underline
or line-through
play a dual role in improving accessibility—enhancing visual emphasis and aiding navigational cues. For example, underlines are widely recognized as signifiers of anchor links, making it easier for users to distinguish interactive elements. Pairing Tailwind's decoration-*
and color utilities ensures that decorations stay clear and functional.
Consider readability for audiences with dyslexia or cognitive impairments. Avoid densely packed underlined text that might overwhelm users; instead, use utilities like underline-offset-*
or increase line height through leading-*
classes to introduce breathing space. Furthermore, judiciously applying text-opacity
or subtle decorations like decoration-dashed
can convey emphasis without adding unnecessary cognitive burden.
Ensure Keyboard Accessibility
Tailwind's text decoration utilities blend naturally with keyboard-focused designs, offering custom states that enhance navigation for users relying on non-pointing devices. Applying focus:underline
on navigable text emphasizes clarity without requiring pointer interactions. Pair this focus strategy with ring-*
utilities for hover-independent validation.
Variations like focus-visible:decoration-4
or decoration-dashed
allow granularity and help distinguish focusable from inactive areas. Nested links within menus, for instance, can adopt hover:underline focus:decoration-double decoration-indigo-700
to blend visual states across interaction types seamlessly.