Custom Text Highlighting with TailwindCSS

Cover Image for Custom Text Highlighting with TailwindCSS
Kevin Graf
Kevin Graf

There are several options out there to enable you to highlight your text or elements. While they are all sufficient to make them pop out, they differ in flexibility of usage and customization capabilities.

The selection of the right solution depends on your personal use case and what you want to achieve. So here is a short summary of available solutions with its use cases including its pro's and con's.

1. Using <mark></mark> to highlight text inline on your page

If you just want to highlight a phrase in your text and you don't want to use bold or italic for some reason, you can easily go with the <mark></mark> tag.

As a default, the highlighted text will be displayed with a bright yellow background like so:

I am highlighted with the <mark></mark> tag

<mark>I am highlighted with the `<mark></mark>` tag</mark>

That bright color can really be a turn-off for a lot of designs, so how are we going to change it?

2. Using CSS and HTML to give your element the necessary style

If the default highlight doesn't suit your page layout style, you are able to add some css to the mark-tag like so:

I am highlighted with a custom background and a wider stroke

<mark class="bg-yellow-300 py-1">
  I am highlighted with a custom background and a wider stroke</mark
>

But there are set some boundaries. What if we want to have the text be highlighted only up to 70% of its size and maybe skew it to make it look more natural? We can't achieve that with styling the mark-tag.

3. Creating a customizable component to highlight various elements

Let's say we want to create a look that tries to imitate a more or less natural text highlighter like this: I am marked in a custom way

We have a slight skew here on the x- and y-axis. Also the marker lies slightly over the text as if we drew over it. So how did we achieve that? Let's take a look at the code:

<span class="relative">
  I am marked in a custom way
  <span
    class="absolute bottom-0 right-0 left-0 opacity-40
     -skew-x-6 -skew-y-1 transform h-3/5 bg-teal-500"
  >
  </span>
</span>

We are placing an absolutely positioned element that is representing the stroke, into a relatively positioned element that is representing the text. That way we are encapsulating the stroke from the text so that we can freely adjust it to our taste. Next we are telling the inner element that it should span over the full width by setting left-0 and right-0. By setting the opacity we can tweak the 'shine-through' effect. Via -skew-x and -skew-y we are calibrating the strokes direction. Finally the h-3/5 is taking care of the amount of height that we want to cover with the stroke.

To make this peace of code reusable and customizable we can wrap it in a React component and extend it with some more features:

import React from 'react'

const Marker: React.FC<{ className?: string, big?: boolean }> = ({
  className,
  big,
  children,
}) => {
  const normalClasses = '-skew-x-6 -skew-y-3 h-1/3'
  const bigClasses = 'mb-1 -skew-x-3 -skew-y-2 h-1/2'
  const markerClasses = big ? bigClasses : normalClasses
  return (
    <div className={'relative group ' + (className ?? '')}>
      {children}
      <span
        className={`absolute bottom-0 right-0 left-0 opacity-40 
        transform group-hover:opacity-60 bg-teal-500 ${markerClasses}`}
      ></span>
    </div>
  )
}

export default Marker

And this is how you would use it in another component:

<Marker className='inline' big>
  I am highlighted
</Marker>

I am highlighted


Feel free to extend the component to your liking!
Happy coding!