Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Align text to the right, overflowing to the left [duplicate]

Tags:

html

css

Note: This question is not answered in the above linked question, nor is it a duplicate. This question addresses the problem with the ordering of special characters when using text-direction: rtl, which it turns out can be solved with the unicode-bidi: bidi-override as pointed out by @Serlite below.

I have a div containing some text that I'd like to overflow to the left, not to the right.

For example, if the div contains all letters of the alphabet, the default behaviour is as follows:

Image 1

I, however, want the contents of the div to be displayed like this:

Image 2

Using direction: rtl in the styles for that div works fine, and achieves this effect perfectly for the above example, as well as if the contents contains just numbers (or a mix of alphanumeric characters) as shown below.

Standard behaviour:

Image 3

Behaviour after setting direction: rtl:

Image 4

The problem occurs when special characters are entered into the div, such as * and #.

Setting the string *#0123456789 as the div contents causes the following to be displayed:

Image 5

Note the * moving from the start of the string to the end.

It's difficult to show the problem with just images, so here is a quick jsfiddle to better demonstrate it.

In general, it seems like weird things happen when setting the direction property, and so I'm guessing it's probably not the way to go.

Is there a way I can force the last characters to always be visible while the first characters overflow to the left?

like image 561
joshfarrant Avatar asked May 10 '16 15:05

joshfarrant


People also ask

Will align text from right to left?

Align the text left or right Select the text that you want to align. On the Home tab, in the Paragraph group, click Align Left or Align Right .

How do I align text to the right span?

If you want to align a <span> element to the right of the <div>, you can use some CSS. Particularly, you need to use the float property with the “right” and “left” values.


2 Answers

The unexpected reordering you're observing is due to an algorithm used for determining the ordering of bi-directional text. I won't go into details on how the ordering is exactly determined, but basically characters are classified by strong, weak, and neutral directionality, which is used to order them in a string.

Your string "*#02468" consists only of a mix of characters with weak or neutral directionality, meaning their ordering may be unexpected without the context of a strongly directional character (like Arabic text, which reads right-to-left). Depending on the characters you use, they may seem to contradict the specified direction.

To avoid this behaviour you're encountering, you can use the unicode-bidi property to override the algorithm, and rely strictly on the specified direction:

#rtl {
  direction: rtl;
  unicode-bidi: bidi-override;
}

Here's an updated JSFiddle.

You can also read up a bit more on the logical ordering of this algorithm, if you're interested. It's a bit too complex to go into detail about.

Hope this helps! Let me know if you have any questions.

Note: If you don't want the characters in your string reversed, this won't work for you. In that case, go with an approach that doesn't use the direction property - because that's exactly what the property was designed for.

like image 200
Serlite Avatar answered Oct 22 '22 09:10

Serlite


EDIT Maybe a less tricky way with text-indent and text-align:

input {
  width: 200px;
  font-size: 30px;
  border:none;
  background:none;
  color:white;
  background:#26A0DA;
}
#rtl {
  text-align: right;
  text-indent: -9999px;
}
label {
  display:inline-block;
  line-height:2em;
  padding:0 5em;
  background:#26A0DA;
  }
  
<label for="ltr">ltr
  <input id="ltr" value="*#02468456789" />
</label>

<label for="rtl">rtl
  <input id="rtl" value="*#02468456789" />
</label>

from my comment, i'll also go with a funny answer : any feed back appreciated

input {
  width: 200px;
  font-size: 30px;
}
label {
  display: inline-block;
  width: 200px;
  overflow: hidden;
  margin:0 2em;
  background:gray;
}
#rtl {
  float: right;
  text-align: right;
  width: 900px;/* whatever */
  margin-left: -900px;/* at least as much as width to give a virtual width close to null, so it sticks at right but do not get pushed  */
}
<label for="ltr">ltr
  <input id="ltr" value="*#abcdefghijklmnopqrstuv" />
</label>

<label for="rtl">rtl
  <br/>
  <input id="rtl" value="*#abcdefghijklmnopqrstuv" />
</label>

https://jsfiddle.net/8zbzy4sL/7/

like image 34
G-Cyrillus Avatar answered Oct 22 '22 09:10

G-Cyrillus