20

Sometimes you don't want an underline blindly cutting through an underlined page title!
Is there a way to automatically elegantly disable underline for certain lowercasee characters? In these cases it's nicer not to underline these lowercase letters like {g,q,p,j, y}

enter image description here

CSS: h1{ text-decoration: underline; }
PAGE TITLE: George quietely jumped!

A) Is there any way one could achieve such a delicate and advanced styling rule?
B) What other Latin characters do we want to un-underline?
C) How to set the thickness/thinness of the underline?

web-tiki
  • 99,765
  • 32
  • 217
  • 249
Sam
  • 15,254
  • 25
  • 90
  • 145
  • 4
    Not possible with CSS on the underline property as it uses the 'baseline' property. – Paulie_D Apr 04 '14 at 15:05
  • You could cheat by putting some bottom padding on the H1 then using border-bottom rather than underline. http://jsfiddle.net/8uP6j/ – Billy Moat Apr 04 '14 at 15:09
  • 2
    the only possible way would be wrapping every letter you wanted to 'un'-underline in a span class and apply `text-decoration: none`, or something equally hacky – celeriko Apr 04 '14 at 15:09
  • 1
    There's a Firefox bug from 2002 to implement what you want, so it's probably not possible: [Bug 156881 - (text-decoration-mode) Underline should skip character/part-of-character that is below the base line](https://bugzilla.mozilla.org/show_bug.cgi?id=156881) – user247702 Apr 04 '14 at 15:11
  • Is that a link? If not, you probably shouldn't underline it in the first place. – DA. Apr 04 '14 at 15:17
  • 1
    I think... Using javascript, you could detect these particular letters, have the javascript wrap them in a span, and put appropriate CSS styles to fix the issue. – Michael Apr 04 '14 at 15:28
  • 1
    Unfortunately, this seems to be impossible. Even after using some jquery to detect a g, and wrap it in CSS. Because the underline is applied as a "whole line" to the H2 element, the span unfortunately won't over-ride it. See this fiddle for a visual demo: http://jsfiddle.net/8Xm5v/ – Michael Apr 04 '14 at 16:19
  • 1
    @Sam, I just understood what "follow up bounty" ment it is now done. – web-tiki Apr 28 '14 at 15:23
  • 2
    @Sam check this out: https://medium.com/designing-medium/7c03a9274f9 – Pat Newell May 02 '14 at 14:12
  • @Sam Please remember that one of the oldest but still valid rules of usability is, that only links should be underlined! ;-) – Netsurfer May 02 '14 at 16:26
  • @Pat Newell +1 for your link! Inspiring! Netsurfer thanks for your critique. Yes that is often valid. – Sam May 04 '14 at 11:46

7 Answers7

26

you can as well fake underline with a border-bottom. this can work for single lines and if display properties allows element to shrink on content. (just avoid block ).

here an example with a display:table to allow center text and break line before and after : http://codepen.io/gc-nomade/pen/vJoKB/ What's the idea ?

  1. setting a smaller line-height than font-size, cause the text to overflow from its container.
  2. draw a bottom border to underline text
  3. SVG offers stroke , in CSS , we can do something similar increasing text-shadow with same color as background.
  4. DEMO , you can even set a different color to the simili underline and add a dropping shadow. result

In older browser you will lose the box-shadow option, but you still can use the double, groove or ridge border styles with different color than text.


Thanks @PatNewell for sharing this very link : https://medium.com/designing-medium/7c03a9274f9

Kyle
  • 65,599
  • 28
  • 144
  • 152
G-Cyrillus
  • 101,410
  • 14
  • 105
  • 129
  • Awesome, I didn't know `text-shadow` could go that far. You can probably just precise they are not supported by IE9 and under http://caniuse.com/css-textshadow – web-tiki Apr 08 '14 at 08:15
  • Sorry was unclear have deleted my post, feel ashamed. I am not as good in this as I thouht. See what I would like is to have the demo of GCyrillus (which has no automatic javascript function, and letter by letter manual css) work with the automatic javascript of web-tiki. This combination will be a better result. True? I have tried some things myself but to no avail helas. Am I still unclear? I must be very stupid :) – Sam Apr 08 '14 at 11:45
  • oki, so just like i said, import css to underline class , so you have both : JS + CSS http://jsfiddle.net/5u44B/46/ – G-Cyrillus Apr 08 '14 at 12:01
  • GCyrillus and @Sam, Both techniques won't work together, as you can see in the fiddle just posted by GCyrillus, the `display:inline-block;` property on `.underline` breaks spaces between words if Sam's point is to add the underlining effect (with 2lines) to my technique, that is not the way to achieve it. – web-tiki Apr 08 '14 at 12:09
  • @Sam maybe this is what you are trying to achieve? http://jsfiddle.net/webtiki/nJeJh/5/ – web-tiki Apr 08 '14 at 12:16
  • 1
    Hi @web-tiki, no this is not what I mean: in your demo the auto generated un-underlines are the full width of a letter so the entire letter "p" is un-underlined. In the demo showed by GCyrillus the un-underlined portions flow graphically around the letters that way its even more nicer! So what I want is his un-underlining shadow styles to be merged with yout automatic javascript solution. Perhaps its time for a second follow up Bounty!?!?! What do you think mate? :) – Sam Apr 19 '14 at 12:16
  • @Sam well, it is shure that graphically it is better you can even choose the color you want to use for the underline and style it in several lines, shadows... From a performance point of view it is also better. The only drawback I can think of is browser compatibility (IE 9 and under). For the bounty, it is up to you! – web-tiki Apr 19 '14 at 12:27
  • @Sam I din't mention it but if I were you I would accept this answer as I am shure it fits your need better. – web-tiki Apr 19 '14 at 13:50
  • This is exactly how I'd do it in print. See [Outline effect to text](http://stackoverflow.com/questions/4919076/outline-effect-to-text) for a discussion. – Jongware May 04 '14 at 21:56
14

This solution uses jQuery to automaticaly wrap the letters to underline in a <span> tag.

DEMO

As parents with text-decoration:underline "override" children with text-decoration:none; (see here). The technique is to wrap only the targeted letters (the ones to underline) with a <span class="underline"> and apply text-decoration:underline; to that class.

Output :

no underline on selected characters with jQuery

Signs that will not be underlined :

g  j  p  q  y  Q  @  {  _  (  )  [  |  ]  }  ;  ,  §  µ  ç  /

HTML :

<h1 class="title">George quietely jumped!</h1>

CSS :

.underline {
    text-decoration:underline;
}

jQuery :

$('.title').each(function () {
    var s = '<span class="underline">',
        decoded;
    $(this).prop('innerHTML', function (_, html) {
        s += html.replace(/&amp;/g, '&').replace(/(g|j|p|q|y|Q|@|{|_|\(|\)|\[|\||\]|}|;|,|§|µ|ç|\/)/g, '</span>$1<span class="underline">');
        s += '</span>'
        $(this).html(s);
    });
});

web-tiki
  • 99,765
  • 32
  • 217
  • 249
  • Awesome mate!! Only little thing: the underline is so thick (it automatically gets thicker as the fontsize grows I guesse) Is there a way to have freedom over the thickness and vertical position of the underline mate? I've tried border-bottom but it seems to want to sit at a distance, not listening to my `margin-top: -5px;` curious... – Sam Apr 07 '14 at 14:16
  • @Sam you can't change the thikness of the underline property and you can't make `border-bottom` closer to the text. See here for the margin issue : http://stackoverflow.com/a/10324608/1811992 You can achieve your goal by setting a background image to the `.underline` class but it won't work if you have multiple lines of text to underline. – web-tiki Apr 07 '14 at 15:29
  • @Sam you can use the `:after` pseudo element to create the underline although it looses all the "semantic" of underlining for SEO --> http://jsfiddle.net/webtiki/nJeJh/3/ – web-tiki Apr 07 '14 at 15:54
  • 1
    @Sam With this technique, you won't loose the SEO semantics for `

    ` tags, first reason : It remains untouched by the script, Second reason JS isn't computed by most crawlers. You will loose the semantics for the underlining though witch is much less important than `

    ` tags.

    – web-tiki Apr 07 '14 at 16:55
  • my bad! I looked better now and see the h1 are intact! I want to award you but need to wait another 9 hours. Your bounty is secured whatever happens Thanks very much @web-tiki! Another strange bizzar problem solved by ingenious creativity with logics! – Sam Apr 07 '14 at 17:03
  • Hi web-tiki and @GCyrillus I found a small bug in our joint effort: when using an ampercent `&`, the character gets strangely converted into html. Is there a fix for this in the JS script? An updated answer would be great. See this demo fiddle exposing the problem: http://jsfiddle.net/ytR8s/ – Sam May 02 '14 at 11:37
  • @Sam , you need to encode htmlentities : see : `.html(encodedStr).text()` – G-Cyrillus May 02 '14 at 11:56
  • @GCyrillus Thanks for the advise! Where do I do that? if you can alter my demo jsfiddle.net/ytR8s then I will provide that new fiddle link as the improved working demo in my question as the answer. – Sam May 02 '14 at 12:05
  • 1
    @Sam I just updated my answer with a fix for the & sign and I also added a whole lot of other signs that need no underline. Tell me if you think of other ones. – web-tiki May 02 '14 at 13:46
  • 2
    hello, well i just did this only for & http://jsfiddle.net/ytR8s/4/ . very nice question indeed :) – G-Cyrillus May 02 '14 at 13:58
  • 1
    @GCyrillus oh yes, that is much neeter! – web-tiki May 02 '14 at 13:59
  • @web-tiki what you did was my first idea when i found out that the .html(encode/decode thingy thing wasn't that easy & efficient to put in action there, untill i remenbered that jquery can take more than one funcion at once – G-Cyrillus May 02 '14 at 14:08
  • 1
    @web-tiki i do not follow you, it only search for the string . i must be missing something here :) – G-Cyrillus May 02 '14 at 14:17
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/51891/discussion-between-web-tiki-and-gcyrillus) – web-tiki May 02 '14 at 14:20
  • Thanks for your updated answer! So far this is the best answer for automatically un-underlining titles. The only remaining challenge is to be able to set the thickness/thinness of the underline. I will set another two bounties for Web-Tiki and @GCyrrillus, as a small token of my esteem, ehum! – Sam May 04 '14 at 11:31
9

Text Decoration Module Level 3 introduces text-decoration-skip

This property specifies what parts of the element's content any text decoration affecting the element must skip over.

You can achieve the behavior you want by setting it to ink:

Skip over where glyphs are drawn: interrupt the decoration line to let the shape of the text show through where the text decoration would otherwise cross over a glyph. The UA must skip a small distance to either side of the glyph outline.

enter image description here

h1 {
  text-decoration: underline;
  text-decoration-skip: ink;
}
<h1>George quietely jumped!</h1>

Note major browsers don't support it yet.

Oriol
  • 274,082
  • 63
  • 437
  • 513
3

If you know your background color (assuming white, in this case), give this a shot:

h1 {
    line-height: 0.9em;
    border-bottom: 1px solid black;
    text-shadow: 2px 2px #fff, -2px 2px #fff;
}

the idea:

  1. use border-bottom, and reduce the line-height to pull the bottom of the h1 box model up.
  2. apply two non-blurred, text shadows which will be rendered behind your text, and over your border-bottom. (The first, in this example, is 2px down and to the left; the second is 2px down and to the right.)

fiddle: http://jsfiddle.net/pmn4/a5LZE/


fyi - browsers don't play nicely with text-shadow; use it conservatively!

Pat Newell
  • 2,219
  • 2
  • 18
  • 23
  • this is exactly what i explain and show in my answer :) , did you read it and followed the DEMO links ? that ws 3 weeks ago or so :p – G-Cyrillus May 02 '14 at 14:11
  • oh! sorry about that @GCyrillus. Completely missed that. – Pat Newell May 02 '14 at 16:25
  • No problem, it was kind of funny to me to see your answer poping out all the sudden. I was tchating with web-tiki at that time right here on that page. :) – G-Cyrillus May 02 '14 at 16:30
  • By the way , thanks for sharing earlier this link https://medium.com/designing-medium/7c03a9274f9, you should add it too to your answer. It tells lots of things :) – G-Cyrillus May 05 '14 at 11:44
2

It would be a pain in the ass, but I would make an "underline" class and then go in and do it manually

HTML

<h1><span class="underline">Ver</span>g<span class="underline">eten Kanalen</span></h1>

CSS

.underline{text-decoration:underline;}
Manly
  • 369
  • 3
  • 18
  • 1
    why is this downvoted? This answers the question (pretty much the only valid answer, for that matter). – DA. Apr 04 '14 at 15:18
  • 2
    It would be more efficient to wrap letters that should not be underlined I do believe as well. – Michael Apr 04 '14 at 15:22
  • 1
    Yea, in hindsight, wrapping the non-underlined letters would be more efficient, but either would work. – Manly Apr 04 '14 at 15:23
  • Could also cut down on HTML by giving the H1 a class of "fix-underline", then leave the spans without classes. CSS selector would be h1.fix-underline span { ... } – Michael Apr 04 '14 at 15:25
  • just my 2p worth: this cannot be automated (as asked by the OP) unless there is a backend platform that can regex the text content and add such span tags - it sounds rather hacky though, and I wouldn't even want to think of JS doing the same (FOUC). Perhaps the best answer is in the first comment made to the question – Luca Apr 04 '14 at 15:54
1

Here is my solution:

Working Fiddle

CSS:

h1, h2 {
  background-image: linear-gradient(to top, transparent 0px, transparent .15em, red .15em, red calc(.15em + 1px), transparent calc(.15em + 1px), transparent 100%);
  text-shadow: 0px -2px 3px white, 0px -2px 3px white, 0px -2px 3px white, 0px -2px 3px white, 0px -2px 3px white, 0px -2px 3px white;
}
Mr_Green
  • 40,727
  • 45
  • 159
  • 271
1

Look into text-decoration-skip-ink CSS property. This can specifies how overlines and underlines are drawn when they pass over glyph ascenders and descenders.

h1 {
  text-decoration: black underline;
  text-decoration-skip-ink: auto;
}
<h1>George quietely jumped!</h1>
Penny Liu
  • 15,447
  • 5
  • 79
  • 98