If you could slightly change the markup by inserting a data-
attribute that contains the same country name e.g.
<ul id="countries">
<li data-country="Afghanistan">Afghanistan</li>
<li data-country="Albania">Albania</li>
<li data-country="Algeria">Algeria</li>
<li data-country="Belgium">Belgium</li>
<li data-country="Belize">Belize</li>
<li data-country="Brazil">Brazil</li>
<li data-country="Canada">Canada</li>
<li data-country="Chile">Chile</li>
</ul>
you could just use CSS like this
li:first-child:before,
[data-country^="A"] + :not([data-country^="A"]):before,
[data-country^="B"] + :not([data-country^="B"]):before,
...,
[data-country^="Y"] + :not([data-country^="Y"]):before {
content: attr(data-country);
display: block;
font-size: inherit;
margin-left: -1em;
overflow: hidden;
width: 2em;
letter-spacing: 100vw;
}
Basically with this solution you write the first data-country
attribute for each letter, but you just show the first letter of the country name thanks to a huge letter-spacing
and a hidden overflow
.
Demo
Note that if you can't manually alter the markup then you could still use this approach by adding dynamically that data-country
attribute via JS like this
let countries = document.querySelectorAll('#countries li');
[...countries].forEach((country) => {
country.dataset.country = country.textContent;
});
No invalid or extra markup and just a bit of javascript in the worst case