JO
184 4
Asked
Updated
Viewed
9.8k times

I'm using the <mark> HTML element to highlight various words in a paragraph, and I'm trying to make it look like someone went over it with an actual marker, vs something symmetrical like a computer would do.

Irregular edges, various opacity across the mark.

I'm also trying to randomize it throughout the paragraph via Javascript so no two highlights are the same to enhance the organic feel of it overall.

So far I've toyed with setting a random border-radius: for each corner, and background-image:linear-gradient(to right, ...); and while those two combined are close, it just doesn't look quite right:

Using linear gradient for CSS highlighter effect

Does anybody have any ideas?

  • 0
    Interesting idea, perhaps take a screenshot of what it looks like so far and update your above question with it. Is it just not looking natural enough? — Brian Wozeniak
  • 0
    I’ll explore this some more when I have time, but I’m not sure you even need JavaScript for this as you can create random numbers in CSS. — Brian Wozeniak
  • 1
    Actually I think you can only do random with Sass and possibly pseudo random with CSS which may still be enough for this effect. — Brian Wozeniak
  • 1
    I've seen "sass" while reading this weekend, I haven't really read up on it yet though. There's a TON of new stuff in CSS since I looked last. — joebert
  • 0
    I looked into a CSS only solution for this and hit two major roadblocks. The first issue is you cannot do pure randomization in CSS; that will require Javascript. So the alternative with CSS would be to pre-compute out some numbers, for example enough border-radius differentiating values that the user would not notice, perhaps 7 or 8 of them. While that is okay, the part that really made it difficult was that nth-child or nth-of-type was not sufficient enough since they would reset once the parent element changes. So as long as these mark elements are all under the same child element or paragraph that might work, but as soon as you create a new paragraph then it would reset and potentially have two identical highlighted elements in a row. The JavaScript solution solves all of this, although I would probably change the Javascript some to instead modify the mark elements style values instead of inserting new mark elements via calling that function. — Brian Wozeniak
add a comment
1

2 Answers

  • Votes
  • Oldest
  • Latest
Answered
Updated

My answer is identical to Joebert's here, except instead of relying on a function to insert mark elements where you likely call the Javascript inline inside your HTML, it instead lets you simply use <mark>highlight this</mark> in your HTML wherever you want without calling ugly Javascript. Thus this is what the code would look like:

mark {
    padding: 0 1ch;
    background: radial-gradient(ellipse, #cc0, #eee);
}
const elements = document.querySelectorAll('mark');
elements.forEach( el => {
    el.style.borderRadius = (0.5 + Math.random()) + 'ch ' + (0.5 + Math.random()) + 'ch ' + (0.5 + Math.random()) + 'ch ' + (0.5 + Math.random()) + 'ch';
});
<p>
    Here is some text that you wrote with an area of <mark>highlighted text</mark>. You can do this <mark>multiple times</mark> and the Javascript above will iterate through each one assigning different border-radius values.
</p>

The Javascript solution here and in Joebert's original does not care about parent elements so you do not run into issues as with a CSS-only solution relying on nth-child or nth-of-type.

add a comment
1
JO
184 4
Answered
Updated

I think I've got something that'll work. The key seems to be using radial-gradient: VS linear-gradient:.

Here's the CSS applied to the <mark> element, where #eee is the background-color: of the parent element. (I couldn't get transparent to work for some reason)

mark {
    padding: 0 1ch;
    background: radial-gradient(ellipse, #cc0, #eee);
}

Then to add some randomness to it I have the following Javascript. (Though I may tweek the radius)

function random_highlighter(css)
{
	return '<mark style="' + (css ? css : '') + 'border-radius: ' + (0.5 + Math.random()) + 'ch ' + (0.5 + Math.random()) + 'ch ' + (0.5 + Math.random()) + 'ch ' + (0.5 + Math.random()) + 'ch;">';
}

The result looks like this:

Using radial gradient for CSS highlighter effect

  • 1
    I agree that the radial gradient definitely improves the effect. Makes it appear softer as well. — Brian Wozeniak
  • 0
    I started playing with ::first-letter and text-shadow trying to get a sort of smeared ink effect, but I haven't been able to get text-shadow and ::first-letter to work together yet. — joebert
add a comment
1