I want to display some text, split into groups of a given length, but retain the ability to search the page for text that spans multiple groups. With this, I want to display some character above each group.
The solution I’ve ended up with is the following one:
body {
margin-top: 1rem;
}
span {
margin-right: 1rem;
position: relative;
}
span::before {
content: "⇣";
position: absolute;
top: -1.2rem;
left: 0;
color: red;
}
<span>This_is_a_sp</span><span>lit_string</span>
Note: the string and split position are hard-coded here, but are dynamically calculated in the real case.
This makes the visual part of the job is perfectly fine, but the problem is that, in Firefox (tested in Chromium, where it works), searching the page for the text split
, which is split between the two groups, gives no results.
Do you have any clue on how to achieve that ? I am not fixed on the way of achieving this (especially the ::before
way), so any idea is welcome ! The only requirement is to use the browser’s native Search in page… tool.
Edit:
I’ve found a Bugzilla bug also reporting this problem. So it seems unlikely to solve it using the ::before
method 😪. Any other solution still welcome !
2
Answers
If the browser’s native search feature is a strict requirement, and since Firefox doesn’t behave like Chromium does when searching content spanning among adjacent elements, an alternative solution might be to just have the whole content joined upfront, and via JS, just add an arrow at given letter positions. That way the search will be performed correctly and yet you’ll have the arrows.
It’s not clear if you can rely on letter positions for those arrows but so far that’s the best I could come up with.
The trick was finding the coords belonging to a given letter position and use them to position a newly created element, holding the arrow, on top of the
.content
div.I used a
monospaced
font that better fits this strategy.In this demo I also addressed a scenario in which the content will overflow the container so the word wrap will kick in. The question let me understand that your content is a stream of adjacent letters not necessarily belonging to real words and not necessarily having spaces.
So I enforced
word-wrap: break-word;
to break words if not containing spaces.Since the arrows position rely on how the text was rendered at the time of their creation, every time the container size changes (because of window resizing), there’s an observer redrawing the arrows when the event occurs. You’ll see when resizing the window, the arrows stick to the same letter they were since the beginning.
A side effect here is not having any space between fragments like you showed in your example. If that’s an important feature to have, I’m afraid this solution is not viable.
It seems the Firefox issue is caused by the pseudo element, because it places itself between the 2 words. If you use
:before
on the firstspan
and:after
on the secondspan
search works on Firefox too.Updated example:
The issue with this solution is that you’re limited to 2 spans, you can’t do something like:
Because the pseudo element again places itself between the 2 words. To make it more clear: