Menu

Tailwind CSS List Style Image

When working with unordered and ordered lists, the list-style-image property in CSS allows you to replace the default bullet or number markers with a custom image. This property comes in handy when designing lists with a custom aesthetic that aligns with a brand's visual guidelines.

In this article, we'll explore the various ways to implement and customize list styles in Tailwind CSS, with step-by-step instructions.

ClassPropertiesExample
list-image-nonelist-style-image: none;<div className="list-image-none"></div>

Overview of List Style Image

Adding the List Style Image

You can use the list-image-* utility classes in Tailwind CSS to assign a custom image to list elements. Tailwind integrates seamlessly with the list-style-image property in to handle custom markers. Here's how to assign an external image as a stylish bullet for a list.

This is a live editor. Play around with it!
export default function StyledList() {  
  return (  
    <div className="w-screen h-screen flex items-center justify-center bg-gray-100">  
      <ul className="list-image-[url('https://images.unsplash.com/photo-1517059224940-d4af9eec41b7?w=20')] list-disc pl-6 space-y-3">  
        {/* Custom image for bullets */}  
        <li className="text-lg text-gray-800">First list item</li>  
        <li className="text-lg text-gray-800">Second list item</li>  
        <li className="text-lg text-gray-800">Third list item</li>  
      </ul>  
    </div>  
  );  
}

States and Responsiveness

Hover and Focus States

Tailwind provides state modifiers to conditionally apply custom list markers on states like hover, focus, etc. Here's how to apply custom list marker images:

This is a live editor. Play around with it!
export default function InteractiveList() {  
  return (  
    <div className="w-screen h-screen flex items-center justify-center bg-gray-100">  
      <ul className="list-disc hover:list-image-[url('https://images.unsplash.com/photo-1517059224940-d4af9eec41b7?w=20')] pl-6 space-y-3">  
        <li className=" text-lg text-gray-900">  
          Interactive first item  
        </li>  
        <li className="text-lg text-gray-900">  
          Interactive second item  
        </li>  
        <li className="text-lg text-gray-900">  
          Interactive third item  
        </li>  
      </ul>  
    </div>  
  );  
}

Breakpoint Modifiers

Responsive designs require list customizations that adapt to different screen sizes. Tailwind provides you with breakpoint modifiers(sm, md, etc.) to modify the list-style-image property for various devices.

This is a live editor. Play around with it!
export default function ResponsiveList() {  
  return (  
    <div className="w-screen h-screen flex items-center justify-center bg-gray-100">  
      <ul className="list-disc pl-8 md:list-image-[url('https://images.unsplash.com/photo-1517059224940-d4af9eec41b7?w=20')] space-y-4">  
        <li className="text-lg text-gray-700">Mobile-first bullet</li>  
        <li className="text-lg text-gray-700">Adapts on medium screens</li>  
        <li className="text-lg text-gray-700">Custom markers for wider displays</li>  
      </ul>  
    </div>  
  );  
}

Custom List Style Image

Extending the Theme

To fully integrate custom values, consider modifying Tailwind's theme in the tailwind.config.js file. By extending the theme, you can register custom utilities for the list-style-image property, making it easier to apply consistently across your project.

In the below example, image URL is saved as custom-marker in the theme file. Now, custom marker can be referenced as list-image-custom-marker when needed:

This is a live editor. Play around with it!
import tailwindConfig from "./tailwind.config.js";
tailwind.config = tailwindConfig;

export default function ThemeExtendedList() {  
  return (  
    <div className="w-screen h-screen flex items-center justify-center bg-gray-100">  
      <ul className="list-image-custom-marker pl-6 space-y-4 text-gray-800">  
        <li>Styled with custom theme</li>  
        <li>Using extended configuration</li>  
        <li>Reusable across components</li>  
      </ul>  
    </div>  
  );  
}

Arbitrary Values for Flexibility

Use arbitrary values in Tailwind if you need to apply a unique marker that isn't predefined. This approach provides absolute flexibility for one-off designs.

Here, the image URL is passed directly using square brackets. Arbitrary values are especially useful in prototyping or when dealing with unique design specifications.

This is a live editor. Play around with it!
export default function ArbitraryStyledList() {  
  return (  
    <div className="w-screen h-screen flex items-center justify-center bg-gray-100">  
      <ul className="list-image-[url('https://images.unsplash.com/photo-1517059224940-d4af9eec41b7?w=20')] pl-7 space-y-5 text-lg">  
        <li>On-the-fly marker styling</li>  
        <li>Quick customization</li>  
        <li>Bypassing predefined options</li>  
      </ul>  
    </div>  
  );  
}

Real World Examples

Product Features List

A modern product features list using custom image as list markers.

This is a live editor. Play around with it!
const FeaturesList = () => {
  const features = [
    {
      title: "Advanced Analytics Dashboard",
      description: "Get deep insights into your business metrics with our interactive dashboard"
    },
    {
      title: "Real-time Collaboration",
      description: "Work together seamlessly with your team members across different time zones"
    },
    {
      title: "Automated Reporting",
      description: "Generate comprehensive reports with just one click"
    },
    {
      title: "Custom Integrations",
      description: "Connect with your favorite tools and services effortlessly"
    },
    {
      title: "Enterprise Security",
      description: "Bank-level encryption and advanced security features to protect your data"
    },
    {
      title: "24/7 Support",
      description: "Get help whenever you need it with our round-the-clock support team"
    }
  ];

  return (
    <div className="max-w-4xl mx-auto p-8">
      <ul className="space-y-6 list-none">
        {features.map((feature, index) => (
          <li 
            key={index} 
            className="pl-8 list-image-[url('https://images.unsplash.com/photo-1633409361618-c73427e4e206?w=20')]"
          >
            <div>
              <h4 className="text-lg font-semibold text-gray-900">{feature.title}</h4>
              <p className="text-gray-600 mt-1">{feature.description}</p>
            </div>
          </li>
        ))}
      </ul>
    </div>
  );
};

export default FeaturesList;

Subscription Benefits

A subscription benefits list of e-commerce platform with custom list image.

This is a live editor. Play around with it!
const BenefitsList = () => {
  const benefits = [
    "Free shipping on all orders",
    "30-day money-back guarantee",
    "Lifetime warranty on products",
    "Premium customer support",
    "Exclusive member discounts",
    "Early access to new products"
  ];

  return (
    <div className="max-w-2xl mx-auto p-6 bg-white shadow-sm rounded-xl">
      <ul className="space-y-3">
        {benefits.map((benefit, index) => (
          <li 
            key={index}
            className="list-image-[url('https://images.unsplash.com/photo-1507925921958-8a62f3d1a50d?w=20')] ml-6 text-gray-700 p-3 border-b border-gray-100 last:border-0"
          >
            {benefit}
          </li>
        ))}
      </ul>
    </div>
  );
};

export default BenefitsList;

Job Requirements

A requirements list of a job listing with custom list image.

This is a live editor. Play around with it!
const RequirementsList = () => {
  const requirements = [
    "5+ years of experience in web development",
    "Strong proficiency in React and TypeScript",
    "Experience with REST APIs and GraphQL",
    "Knowledge of CI/CD pipelines",
    "Excellent problem-solving skills",
    "Good communication and teamwork abilities"
  ];

  return (
    <div className="max-w-2xl mx-auto p-6">
      <ul className="space-y-3 bg-blue-50 p-4 rounded-lg">
        {requirements.map((requirement, index) => (
          <li 
            key={index}
            className="list-image-[url('https://images.unsplash.com/photo-1634896941598-b6b500a502a7?w=20')] ml-6 text-blue-900 p-2 bg-blue-100/50 rounded"
          >
            {requirement}
          </li>
        ))}
      </ul>
    </div>
  );
};

export default RequirementsList;

Installation Steps

A list of installation steps with custom list image.

This is a live editor. Play around with it!
const StepsList = () => {
  const steps = [
    "Download and install the application",
    "Create your account and verify email",
    "Set up your profile information",
    "Configure your preferences",
    "Connect your social accounts",
    "Start using the platform"
  ];

  return (
    <div className="max-w-2xl mx-auto p-6 bg-gradient-to-br from-gray-50 to-white">
      <ul className="space-y-4">
        {steps.map((step, index) => (
          <li 
            key={index}
            className="list-image-[url('https://images.unsplash.com/photo-1614036417651-efe5912149d8?w=20')] ml-6 text-gray-700 pl-2"
          >
            <span className="font-medium text-gray-900">Step {index + 1}:</span> {step}
          </li>
        ))}
      </ul>
    </div>
  );
};

export default StepsList;

Documentation Menu Items

A list of doc menu items with custom list images.

This is a live editor. Play around with it!
const ResourcesList = () => {
  const resources = [
    "Getting Started Guide",
    "API Documentation",
    "Video Tutorials",
    "Sample Projects",
    "Community Forums",
    "FAQs and Troubleshooting"
  ];

  return (
    <div className="max-w-2xl mx-auto p-6">
      <ul className="space-y-3 bg-emerald-50 p-4 rounded-lg">
        {resources.map((resource, index) => (
          <li 
            key={index}
            className="list-image-[url('https://images.unsplash.com/photo-1623282033815-40b05d96c903?w=20')] ml-6 text-emerald-800 bg-emerald-100/50 px-4 py-2 rounded-full"
          >
            {resource}
          </li>
        ))}
      </ul>
    </div>
  );
};

export default ResourcesList;

Customization Examples

Nature-themed Checklist

This example creates a nature-themed checklist using leaf images as bullet points.

This is a live editor. Play around with it!
import tailwindConfig from "./tailwind.config.js";
tailwind.config = tailwindConfig;

export default function NatureChecklist() {
  return (
    <div className="min-h-screen bg-green-50 p-8">
      <div className="max-w-2xl mx-auto bg-white rounded-xl shadow-lg p-6">
        <h2 className="text-2xl font-bold text-green-800 mb-4">
          Garden Maintenance Tasks
        </h2>
        <ul className="list-image-leaf ml-6 space-y-3">
          <li className="text-green-700 pl-2">Water the plants daily</li>
          <li className="text-green-700 pl-2">Trim the hedges</li>
          <li className="text-green-700 pl-2">Remove fallen leaves</li>
          <li className="text-green-700 pl-2">Check soil moisture</li>
          <li className="text-green-700 pl-2">Fertilize monthly</li>
        </ul>
      </div>
    </div>
  )
}

Tech Documentation Markers

This example uses custom arrow markers for a technical documentation list.

This is a live editor. Play around with it!
import tailwindConfig from "./tailwind.config.js";
tailwind.config = tailwindConfig;

export default function TechDocumentation() {
  return (
    <div className="min-h-screen bg-gray-900 p-8">
      <div className="max-w-3xl mx-auto bg-gray-800 rounded-lg p-8">
        <h2 className="text-3xl font-bold text-blue-400 mb-6">
          Installation Steps
        </h2>
        <ul className="list-image-arrow ml-8 space-y-4">
          <li className="text-gray-300 pl-4 border-b border-gray-700 pb-2">
            Clone the repository from GitHub
          </li>
          <li className="text-gray-300 pl-4 border-b border-gray-700 pb-2">
            Install dependencies using npm
          </li>
          <li className="text-gray-300 pl-4 border-b border-gray-700 pb-2">
            Configure environment variables
          </li>
          <li className="text-gray-300 pl-4 border-b border-gray-700 pb-2">
            Run database migrations
          </li>
          <li className="text-gray-300 pl-4">
            Start the development server
          </li>
        </ul>
      </div>
    </div>
  )
}

Recipe Ingredients List

This example uses custom food icons for a recipe ingredients list.

This is a live editor. Play around with it!
import tailwindConfig from "./tailwind.config.js";
tailwind.config = tailwindConfig;

export default function RecipeIngredients() {
  return (
    <div className="min-h-screen bg-amber-50 p-8">
      <div className="max-w-xl mx-auto bg-white rounded-2xl shadow-xl p-8">
        <h2 className="text-3xl font-serif text-amber-800 mb-6">
          Classic Pasta Recipe
        </h2>
        <div className="bg-amber-100 rounded-lg p-6">
          <h3 className="text-xl font-semibold text-amber-900 mb-4">
            Ingredients Needed:
          </h3>
          <ul className="list-image-ingredient ml-6 space-y-4">
            <li className="text-amber-900 pl-4 font-medium">
              400g Fresh Pasta
            </li>
            <li className="text-amber-900 pl-4 font-medium">
              2 cloves of Garlic
            </li>
            <li className="text-amber-900 pl-4 font-medium">
              3 tbsp Olive Oil
            </li>
            <li className="text-amber-900 pl-4 font-medium">
              Fresh Basil Leaves
            </li>
            <li className="text-amber-900 pl-4 font-medium">
              Grated Parmesan
            </li>
          </ul>
        </div>
      </div>
    </div>
  )
}

Best Practices

Maintain Design Consistency

Extend the Tailwind's theme in tailwind.config.js file to define reusable custom marker styles. For instance, you can create a branded bullet style and apply it uniformly across multiple components. This not only simplifies maintenance but also ensures your list designs remain visually aligned with the rest of your application.

By defining a custom listStyleImage property like primary-icon, you can reference it as a utility class (list-image-primary-icon). This centralizes updates and ensures all instances of the style remain consistent in case of design changes. Always consider the reusability of your markers to avoid unnecessary redundancy.

Balance with Other Layout Properties

Ensuring that list-style-* integrates well with other layout properties prevents unexpected design inconsistencies. For instance, combining list-inside with leading-relaxed creates a visually appealing list format by managing spacing between list items while keeping markers properly aligned with the text.

If working with flex or grid-based layouts, lists should be structured to complement surrounding elements. Additionally, use responsive padding (e.g., sm:pl-3 md:pl-6, etc.) to ensure that list items remain properly spaced and visually distinct across different screen sizes.

Accessibility Considerations

Enhance Readability and Navigability

One of the key considerations when using list-style-image is ensuring that it does not disrupt the logical reading order. By carefully selecting appropriate marker images and combining them with Tailwind’s list-inside utility, you can maintain a structured and accessible layout.

The list-inside ensures that list markers remain within the text flow rather than appearing outside the content block, which can be particularly helpful for screen reader users. Additionally, pairing this utility with appropriate spacing values to control the spacing between list items, preventing them from appearing cluttered or difficult to follow.

Focus on High Contrast

When using list style image, ensure high contrast between list markers and text to maintain readability. Low-contrast markers can blend into the background, making it difficult for users to distinguish individual list items.

One way to achieve high contrast is by choosing list images with distinct colors that stand out against the background. If your list items use a light background, opt for dark or bold-colored markers, and vice versa. Tailwind’s utility classes like invert, brightness-*, and contrast-* can be applied to refine the appearance of custom list markers. These adjustments ensure that markers maintain sufficient visibility even under different UI themes, including dark mode.