Home > Blockchain >  What unicode spaces are equal to letter widths?
What unicode spaces are equal to letter widths?

Time:12-21

I am trying to replace some letters of a text (in a non monospace font) with spaces of same width.

Is it possible? How? Are there any non-monospace fonts that allow this?

I found these unicode spaces, and apparently U 2002 is an EN SPACE and U 2003 an EM SPACE. But the widths don't always match.

<p>the en space looks nice</p>
<p>the e&#x2002; space looks &#x2002;ice</p>

<p>but em space has more width</p>
<p>but e&#x2003; space has &#x2003;ore width</p>

And I wonder what spaces should I use for other letters...

I know I could set transparency or color to individual letters. But I wanted to find an easy solution with spaces.

CodePudding user response:

Your question was interesting so I thought about the fact that you wanted a real space instead of the missing char, typically for a copy-paste operation. Using CSS pseudo-elements could be a solution because the content of them isn't used for text selection.

The space chars have a fixed width, which is not the case for letters since a m is wider than a i. I think that EM space is 1 em wide and EN space is 0.5 em.

So my idea was to replace your char, let's say m, by this:

<span  data-char="m"><span>&nbsp;</span></span>

Yes, this is a lot of HTML and you are asking yourself "why having an inner span?". Well, the problem is that we want the space to have no width and we want the pseudo-element to take this space instead. I also noticed that if you replace the non-breaking space &nbsp; by the normal space &#32; then you get no space at all when you select the text for a copy-paste.

I came out to this solution:

span.pseudo-space {
  position: relative; /* Child span will be absolute. */
  overflow: hidden; /* Just to avoid a potential scrollbar. */
}
span.pseudo-space > span {
  position: absolute; /* Avoid width calculation on the parent span. */
}
span.pseudo-space::after {
  content: attr(data-char); /* Display the original char. */
  color: transparent;
}

/* Just to have a gray block to see the text aligned. */

blockquote {
  margin: 0.5em 0;
  padding: 1em;
  background: #eee;
  display: inline-block;
}
blockquote p:first-child {
  margin-top: 0;
}
blockquote p:last-child {
  margin-bottom: 0;
}
<blockquote>
  <p>The "n" character will never be the same width as a space character.</p>
  <p>The "<span  data-char="n"><span>&nbsp;</span></span>" character will <span  data-char="n"><span>&nbsp;</span></span>ever be the same width as a space character.</p>

  <p>The "m" character will never be the same width as a space character.</p>
  <p>The "<span  data-char="m"><span>&nbsp;</span></span>" character will never be the sa<span  data-char="m"><span>&nbsp;</span></span>e width as a space character.</p>
</blockquote>

Try to copy-paste the content of the blockquote and you should normally get the space instead of the hidden char. (Tested on Chrome, Firefox and Edge).

CodePudding user response:

I wanted to do something like this. If I could replace letters with spaces of the same width, it would be much easier. I wouldn't need to play with HTML elements and style.

// Convert letter to spans with opacity:0
const p = document.querySelector("p");
p.innerHTML = p.innerText
  .split("")
  .map(c => `<span style='opacity: 0'>${c}</span>`)
  .join("");

const letterSpans = p.querySelectorAll('span');

// Create random sequence of indexes
const indexes = Array(letterSpans.length).fill().map((e, i) => i)
indexes.sort((a, b) => 0.5 - Math.random());

// Display letters in the order indicated by `indexes`
function displayLetterAtIndex(i) {
  letterSpans[indexes[i]].style.opacity = 1;
  if (i < letterSpans.length - 1) {
    setTimeout(() => displayLetterAtIndex(i 1), 50);
  }
}
displayLetterAtIndex(0);
<p>Letters will appear in a random order</p>

  • Related