How to change line break order when using bidi-override and right-to-left direction with CSS?

179 Views Asked by At

I'm using a little script which hides mail addresses using the fact that you can reverse text by using unicode-bidi: bidi-override and direction: rtl.

<span>
    <span>moc.e</span>
    <span>ussi-</span>
    <span>kaerb</span>
    <span>-enil</span>
    <span>@sser</span>
    <span>dda-l</span>
    <span>iam-t</span>
    <span>set</span>
</span>

With the following output:

[email protected]

Unfortunately, this doesn't work when the mail address is too long and contains a line-break:

screenshot line break issue

The reverse text direction causes that the end of the mail address comes before the line break:

-break-issue.com
test-mail-address@line

Check out the code snippet:

div {
  display: inline-block;
  margin: 0 10px 10px 0;
  padding: 10px;
  vertical-align: top;
  font-size: small;
}

.small {
  border: 1px solid red;
  width: 170px;
}

.big {
  border: 1px solid green;
  width: 280px;
}

strong {
  display: block;
  margin-bottom: 30px;
}

span.eeb-rtl {
  unicode-bidi: bidi-override !important;
  direction: rtl !important;
  display: inline !important;
}

span.eeb-rtl span.eeb-sd {
  display: inline !important;
  padding-left: 0 !important;
}
<div class="small">
  <strong>Small container</strong>
  <span class="eeb eeb-rtl">
    <span class="eeb-sd">moc.e</span><span class="eeb-sd">ussi-</span><span class="eeb-sd">kaerb</span><span class="eeb-sd">-enil</span><span class="eeb-sd">@sser</span><span class="eeb-sd">dda-l</span><span class="eeb-sd">iam-t</span><span class="eeb-sd">set</span>
  </span>
</div>
<div class="big">
  <strong>Big container</strong>
  <span class="eeb eeb-rtl">
    <span class="eeb-sd">moc.e</span><span class="eeb-sd">ussi-</span><span class="eeb-sd">kaerb</span><span class="eeb-sd">-enil</span><span class="eeb-sd">@sser</span><span class="eeb-sd">dda-l</span><span class="eeb-sd">iam-t</span><span class="eeb-sd">set</span>
  </span>
</div>

Is there any CSS option to correct the line breaking order in a small container?

The result should be:

test-mail-address@line-
break-issue.com
2

There are 2 best solutions below

4
Zachiah On BEST ANSWER

This is a very dirty solution but hey it works ¯\_(ツ)_/¯ . I changed the classnames because I was having a hard time following the code btw.

div {
  display: inline-block;
  margin: 0 10px 10px 0;
  padding: 10px;
  vertical-align: top;
  font-size: small;
}

.small {
  border: 1px solid red;
  width: 170px;
}

.big {
  border: 1px solid green;
  width: 280px;
}

strong {
  display: block;
  margin-bottom: 30px;
}



.text-piece {
  unicode-bidi: bidi-override;
  direction: rtl;
}

/* Add enough to cover all of your segments */
.text-piece:nth-last-child(1) {order:1}
.text-piece:nth-last-child(2) {order:2}
.text-piece:nth-last-child(3) {order:3}
.text-piece:nth-last-child(4) {order:4}
.text-piece:nth-last-child(5) {order:5}
.text-piece:nth-last-child(6) {order:6}
.text-piece:nth-last-child(7) {order:7}
.text-piece:nth-last-child(8) {order:8}
.text-piece:nth-last-child(9) {order:9}
.text-piece:nth-last-child(10) {order:10}

.wrapper-span {
  display: flex;
  flex-wrap: wrap;
}
<div class="small">
  <strong>Small container</strong>
  <span class="wrapper-span">
    <span class="text-piece">moc.e</span><span class="text-piece">ussi-</span><span class="text-piece">kaerb</span><span class="text-piece">-enil</span><span class="text-piece">@sser</span><span class="text-piece">dda-l</span><span class="text-piece">iam-t</span><span class="text-piece">set</span>
</div>
<div class="big">
  <strong>Big container</strong>
  <span class="wrapper-span">
    <span class="text-piece">moc.e</span><span class="text-piece">ussi-</span><span class="text-piece">kaerb</span><span class="text-piece">-enil</span><span class="text-piece">@sser</span><span class="text-piece">dda-l</span><span class="text-piece">iam-t</span><span class="text-piece">set</span>
  </span>
</div>

1
imhvost On

I'm assuming you want to prevent web scraping, so you're displaying email like this. If you are already using "little script", the best solution is to improve it. With your permission I am trying to reproduce your script. I'm giving you a javascript code example but you can easily transfer to any other programming language like php, becase I think this one should happen on the backend side.

const email = '[email protected]';

small.innerHTML = convertEmail(email);
big.innerHTML = convertEmail(email);

function convertEmail(email) {
  return '<span class="email">' + 
    email.split('')
         .reverse()
         .join('')
         .match(/.{1,5}/g)
         .map( (el, index) => `<span style="order:${index * -1}">${el}</span>` )
         .join('')
  + '</span>';
}
body {
  display: flex;
  gap: 16px;
}

#small {
  border: solid 1px red;
  padding: 10px;
  width: 170px;
}

#big {
  border: solid 1px green;
  padding: 10px;
}

.email {
  display: flex;
  flex-wrap: wrap;
}

.email span {
  unicode-bidi: bidi-override;
  direction: rtl;
}
<div id="small"></div>
<div id="big"></div>