How can I remove letter-spacing for the last letter of an element in CSS?
Asked Answered
C

8

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;
}
Chalcedony answered 4/8, 2011 at 23:31 Comment(0)
A
71

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/

Amatory answered 4/8, 2011 at 23:36 Comment(6)
The :first-letter pseudo-element isn't exactly "per character" either (otherwise it'd be called :first-character). See #5649796Frenzy
ended up on this one while wanting to have a text-decoration: underline… in that case it does not work. Any clue ?Melburn
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).Nonbeliever
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).Nonbeliever
This works for the case, but when you have text-decoration: underline; the space still there.Collete
note - margin-right on an element with transform: rotate(90deg); does not work.. the margin-{direction} must match the rotation of the element..Virgenvirgie
B
29

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.

Basanite answered 4/8, 2011 at 23:49 Comment(6)
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.Chalcedony
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.Basanite
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.Chalcedony
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.Basanite
Seems to a bug for a while already (but it may be fixed with full css3 implementation): bugzilla.mozilla.org/show_bug.cgi?id=125390Sour
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" drafts.csswg.org/css-text/#letter-spacing-propertyDartboard
O
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>
Outfit answered 9/10, 2019 at 23:24 Comment(1)
This is the most voodoo-ish of CSS hacks I've seen in a while, that actually works. Very clever.Rabid
B
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

Berserk answered 10/11, 2020 at 12:1 Comment(0)
D
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 :)

Dubenko answered 4/8, 2011 at 23:45 Comment(2)
Um, :first-letter has been there since CSS1.Frenzy
This is a bad idea since screen readers and search engines would get content with missing characters.Mathi
K
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.

Kurdish answered 21/7, 2020 at 20:30 Comment(0)
A
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);
}
Alleviation answered 17/8, 2020 at 9:19 Comment(0)
B
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>
Burton answered 15/4, 2022 at 6:53 Comment(2)
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.Chalcedony
This is bad for a number of reasons. Every software that is trying to access the content programmatically (search engines, screen readers) will be faced with broken words because of the missing letter in the end.Mathi

© 2022 - 2024 — McMap. All rights reserved.