65

Here's the image in question of my HTML page. The text menu is inside a right aligned div, and has 1.2em letter spacing. Is there a pseudo-selector for this? I would not like to have to resort to relative positioning.

I would love the text menu to end where the block ends.

Right text-aligned div where letter spacing applies for all characters of a line

I've already marked the best answer, but I was asked for the markup regardless by CodeBlock. Here it is.

<div class="sidebar">
    <span class="menuheader">MENU</span>
    <ul>
        <li><a href="#content">Content</a></li>
        <li><a href="#attachments">Attachments</a></li>
        <li><a href="#subpages">Sub-pages</a></li>
        <li><a href="#newsubpage">New sub-page</a></li>
        </a>
    </ul>
</div>
.sidebar {
    color: rgb(150,93,101);
    display: inline;
    line-height: 1.3em;
    position: absolute;
    top: 138px;
    width: 218px;
}
    
.menuheader {
    letter-spacing: 1.1em;
    margin: -1.2em;
    text-align: right;
}
desbest
  • 4,746
  • 11
  • 51
  • 84

8 Answers8

69

You can set your element to have a right margin of -1.2em, which would counteract the letter spacing.

e.g.

.menu-header-selector {
  display:block;
  letter-spacing:1.2em;
  margin-right:-1.2em;
  text-align:right;
}

To answer your question regarding pseudo-selector, there isn't a per character pseudo-selector as far as I'm aware. (EDIT: Scratch that, there's the :First-Letter selector, which Jonas G. Drange pointed out).

EDIT: You can find a basic sample here: http://jsfiddle.net/teUxQ/

Karl Nicoll
  • 16,090
  • 3
  • 51
  • 65
  • 1
    The `:first-letter` pseudo-element isn't exactly "per character" either (otherwise it'd be called `:first-character`). See http://stackoverflow.com/questions/5649296/css-pseudo-element-to-apply-the-first-characther-of-an-element/5649347#5649347 – BoltClock Aug 05 '11 at 07:27
  • 1
    ended up on this one while wanting to have a text-decoration: underline… in that case it does not work. Any clue ? – Ben Oct 21 '14 at 18:27
  • 1
    This solution is a pretty good fix, but if you want to have `text-align: center` another option that builds on this idea is to instead set `margin-left` to **.5 * `letter-spacing`** (`.6em` in the above example) and `margin-right` to **-.5 * `letter-spacing`** (`-.6em` for the above example -- note the `right-margin` is a **negative** value). – CoderScissorhands Sep 07 '16 at 12:39
  • sorry typo at the end of my above comment: it should read "note the `margin-right` is a **negative** value" (I missed the five minute editing window by seconds). – CoderScissorhands Sep 07 '16 at 12:46
  • 2
    This works for the case, but when you have `text-decoration: underline;` the space still there. – Carlos Oliveira Sep 01 '17 at 17:01
  • note - `margin-right` on an element with `transform: rotate(90deg);` does not work.. the `margin-{direction}` must match the rotation of the element.. – grgry Sep 21 '17 at 09:31
27

I would call this a browser bug, actually. The spec says it's the spacing between characters, while your browser (and mine) seem to be changing the spacing after characters. You should submit a bug report.

LaC
  • 12,624
  • 5
  • 39
  • 38
  • I was using Opera 11.50. The latest version. I like slicing pure css designs in Opera, as Firefox renders too perfectly, and IE9 might have quirks. – desbest Aug 05 '11 at 00:11
  • 1
    Yes. That's why you have to submit a bug report. If it had been an old version, I would have told you to update first. – LaC Aug 05 '11 at 00:57
  • I don't think submitting a bug report will be a good idea, as IE/FF/WK/OP would have to all implement this quirk. Also that if the bug is fixed, it would impact the design of other websites negatively I think. – desbest Aug 05 '11 at 22:00
  • 5
    Maybe you're thinking about how your own website will be impacted if you implement a workaround and then the bug gets fixed. But be careful: this kind of reasoning is what got us stuck with IE6 for years. – LaC Aug 05 '11 at 23:05
  • Seems to a bug for a while already (but it may be fixed with full css3 implementation): https://bugzilla.mozilla.org/show_bug.cgi?id=125390 – Roderik Oct 20 '18 at 02:07
  • Wow, this is still an issue in 2021. The spec clearly says "When letter-spacing is not applied at the beginning or end of a line, text always fits flush with the edge of the block. UAs therefore really should not [RFC6919] append letter spacing to the right or trailing edge of a line" https://drafts.csswg.org/css-text/#letter-spacing-property – lschult2 Sep 17 '21 at 16:37
8

Obviously a very old question, but CSS involved for your specific example worked at that time.

It involves to reset direction to the opposite, give a formating context to your inline element and set a negative text-indent equal to the letter spacing.

Demo below:

.sidebar {
  color: rgb(150, 93, 101);
  line-height: 1.3em;
  width: 218px;
  border:solid;
  text-align:right;
}

.menuheader {
  letter-spacing: 1.1em;
  direction:rtl;
  display:inline-block;
  text-indent:-1.1em;
  background:gold
}
<div class="sidebar">
  <span class="menuheader">MENU</span>
  <ul>
    <li><a href="#content">Content</a></li>
    <li><a href="#attachments">Attachments</a></li>
    <li><a href="#subpages">Sub-pages</a></li>
    <li><a href="#newsubpage">New sub-page</a></li>
  </ul>
</div>
G-Cyrillus
  • 101,410
  • 14
  • 105
  • 129
6

You can add an :after of your element and set a minus margin left equal as the letter-spacing

.menuheader {
  letter-spacing: 1.1em;
}
    
.menuheader:after {
   content:" ";
   margin-left:  -1.1em;
}

Tested on Chrome, Firefox and Edge

Macumbaomuerte
  • 2,197
  • 2
  • 19
  • 22
4

You cannot target the last character, only the first (CSS3, :first-letter). You can add a span around the last letter, but that would mean adding meaningless markup which is "worse" than adding positioning to the element.

CSS is perfect for trickery like this :)

Jonas G. Drange
  • 8,749
  • 2
  • 27
  • 38
1

No need for changing display to any other kind (<p> paragraph example) or actually doing anything unnecessary with my code. Text-indent set to negative letter-spacing value resolves that problem for me.

text-indent: -2em; works exactly as I want for letter-spacing: 2em; and was the only thing I had to add to my CSS.

pawelduzy
  • 41
  • 2
0

You could try adding display: block to the text and then reduce the width by using 100% minus the letter-spacing.

.menuheader {
 text-align: right;
 display: block; 
 letter-spacing: 1.1em; 
 width: calc(100% - 1.1em);
}
siaeva
  • 143
  • 2
  • 11
0

I think i have the best answer

You can use ::after and set content as the last word of your word

div{
display:inline-block;}

#demo1{border: 2px blue dashed; 
    text-align: center;
    letter-spacing: 3vw;
}

#demo2{border: 2px blue dashed; 
    text-align: center;
    letter-spacing: 3vw;}

#demo2::after{
content:'g';
letter-spacing:0;}
<div id="demo1">something</div><span>  ///here after last letter their is a gap</span></br> </br>
<div id="demo2">somethin</div> <span>///here the gap is removed with the help of ::after sudeo class</span>
Ajay Sahu
  • 186
  • 1
  • 7
  • Can you give an answer without putting the last character in the `content:` attribute? What if the text is being dynamically generated from a blog script like Wordpress? Then my CSS code won't be able to predict what letter is last. – desbest Apr 15 '22 at 09:01