Menu

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.

ClassPropertiesExample
underlinetext-decoration-line: underline;<div className="underline"></div>
overlinetext-decoration-line: overline;<div className="overline"></div>
line-throughtext-decoration-line: line-through;<div className="line-through"></div>
no-underlinetext-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;

This is a live editor. Play around with it!
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;

This is a live editor. Play around with it!
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;

This is a live editor. Play around with it!
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;

This is a live editor. Play around with it!
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.

This is a live editor. Play around with it!
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.

This is a live editor. Play around with it!
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.

This is a live editor. Play around with it!
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.

This is a live editor. Play around with it!
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>
  );
}

A navigation menu component with a double underline effect on active items.

This is a live editor. Play around with it!
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.

This is a live editor. Play around with it!
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.

This is a live editor. Play around with it!
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.

This is a live editor. Play around with it!
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.

This is a live editor. Play around with it!
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.