CSS Text underlining too long when letter-spacing is applied?

前端 未结 7 1170
别那么骄傲
别那么骄傲 2020-11-29 11:00


Whenever letter-spacing is applied to something with an underline or a bottom border, it seems like the underline extends beyond the text on the right. Is

相关标签:
7条回答
  • 2020-11-29 11:39

    As far as I know, there’s nothing you can do about this. I guess most browsers add letter spacing after each letter, including the last one. There aren’t any CSS properties that offer finer control over letter spacing.

    This seems to solve the issue, sort-of, in Firefox 3.6 on my Mac, but it’s not super-practical to do this for every underlined element either.

    <span style="border-bottom: 1px solid black;">
        <span style="letter-spacing: 1em;">Tes</span>t
    </span>
    
    0 讨论(0)
  • 2020-11-29 11:48

    Thanks for the responses, I suppose it is a limitation of css/html. Luckily these links were being put in via php so I wrote a script to surround them appropriately, although not an entirely ideal solution, it works:

    $part1 = substr($string, 0, -1);
    $part2 = substr($string, -1);
    $full = "<span style='letter-spacing: 1em'>".$part1."</span><span>".$part2."</span>";
    

    (the second span for the last letter I included so I could apply a style with no letter-spacing when I needed to wrap the whole element in a link or something else with an underline etc)

    Too bad the control for underlines is rather limited with html/css (especially trying to define the distance between the line and the text, thickness etc), but I suppose this works for now.

    0 讨论(0)
  • 2020-11-29 11:49

    The problem is that "letter-spacing" adds space by adding white space after each letter, but this space belongs to the letter, and thus the last one has an extra underline that makes it look like it's expanding beyond the last letter (if you select with the mouse the last letter of the div, you'll see what I mean).

    You could solve it by having the last letter of the text block not having the "letter-spacing" property. For example:

    <span style="letter-spacing: 1em; text-decoration: underline;">SPACEEE</span>
    <span style="text-decoration: underline;">.</span>
    

    It's far from ideal, but unless it's just a one line text (there, you could use a negative margin to the right), I can't think of any other solution.

    0 讨论(0)
  • 2020-11-29 11:54

    It's not perfect, but the best solution I have come up with so far is to mask it with a :after pseudo element. This way there's no need for extra elements throughout your text.

    For example:

    h1 {
      /* A nice big spacing so you can see the effect */
      letter-spacing: 1em;
      /* we need relative positioning here so our pseudo element stays within h1's box */
      position: relative;
      /* centring text throws up another issue, which we'll address in a moment */
      text-align: center;
      /* the underline */
      text-decoration: underline;
    }
    
    h1:after {
      /* absolute positioning keeps it within h1's relative positioned box, takes it out of the document flow and forces a block-style display */
      position: absolute;
      /* the same width as our letter-spacing property on the h1 element */
      width: 1em;
      /* we need to make sure our 'mask' is tall enough to hide the underline. For my own purpose 200% was enough, but you can play and see what suits you */
      height: 200%;
      /* set the background colour to the same as whatever the background colour is behind your element. I've used a red box here so you can see it on your page before you change the colour ;) */
      background-color: #990000;
      /* give the browser some text to render (if you're familiar with clearing floats like this, you should understand why this is important) */
      content: ".";
      /* hide the dynamic text you've just added off the screen somewhere */
      text-indent: -9999em;
      /* this is the magic part - pull the mask off the left and hide the underline beneath */
      margin-left: -1em;
    }
    
    <h1>My letter-spaced, underlined element!</h1>
    

    And that's it!

    You can also use borders if you want finer control over colour, positioning, etc but these require you to add a span element unless you have a fixed width.

    For example, I'm currently working on a site which requires h3 elements to have 2px letter spacing, centred text and an underline with added space between the text and the underline. My css is as follows:

    h3.location {
      letter-spacing: 2px;
      position: relative;
      text-align: center;
      font-variant: small-caps;
      font-weight: normal;
      margin-top: 50px;
    }
    
    h3.location span {
      padding-bottom: 2px;
      border-bottom: 1px #000000 solid;
    }
    
    h3.location:after {
      position: absolute;
      width: 2px;
      height: 200%;
      background-color: #f2f2f2;
      content: ".";
      text-indent: -9999em;
      margin-left: -2px;
    }
    

    and my HTML is:

    <h3><span>Heading</span></h3>
    

    Notes:

    It's not 100% pretty CSS but it does at least mean you don't have to modify & hack your HTML to achieve the same result.

    I haven't yet had to try this on an element with a background image, so haven't yet thought of a method of achieving this.

    Centring text makes the browser display the text in the wrong place (it accounts for the text + extra spacing afterwards), so everything is pulled left. Adding a text-indent 0.5em (half the 1em letter spacing we used in the top example) directly on the h1 element (not the :after pseudo element) should fix this, though I've not tested this yet.

    Any feedback is gratefully received!

    Neal

    0 讨论(0)
  • 2020-11-29 11:55

    I wouldn't break tex<span>t</span> for SEO reasons, so I prefer to replace the underline with a fake one. CSS calc can help you with its width.

    a{
      text-decoration:none;
      letter-spacing:15px;
      color:red;
      display:inline-block;
    }
    
    a .underline{
      height:2px;
      background-color:red;
      width: calc(100% - 15px); /*minus letter spacing*/
    }
    <a href="#">Text
    <div class="underline"></div></a>

    0 讨论(0)
  • 2020-11-29 11:56

    If you don't want to split the last letter of "Test", you can just wrap it with a span and do this:

    span {
        letter-spacing: 1.1em;
        margin-right: -1.1em;
    }
    

    As you can see it even works with elastic units. If don't have a custom margin on a, you can skip adding the span and apply this style directly to a

    It works wonders for me =)

    0 讨论(0)
提交回复
热议问题