Disable underline for lowercase characters: g q p j y?
Asked Answered
L

7

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?

Logical answered 4/4, 2014 at 15:2 Comment(11)
Not possible with CSS on the underline property as it uses the 'baseline' property.Grandiose
You could cheat by putting some bottom padding on the H1 then using border-bottom rather than underline. jsfiddle.net/8uP6jSemiquaver
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 hackyPoppo
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 lineCuneal
Is that a link? If not, you probably shouldn't underline it in the first place.Sherrisherrie
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.Micromillimeter
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: jsfiddle.net/8Xm5vMicromillimeter
@Sam, I just understood what "follow up bounty" ment it is now done.Crete
@Logical check this out: medium.com/designing-medium/7c03a9274f9Cloistral
@Logical Please remember that one of the oldest but still valid rules of usability is, that only links should be underlined! ;-)Unearth
@Pat Newell +1 for your link! Inspiring! Netsurfer thanks for your critique. Yes that is often valid.Logical
A
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

Avidin answered 7/4, 2014 at 23:0 Comment(9)
Awesome, I didn't know text-shadow could go that far. You can probably just precise they are not supported by IE9 and under caniuse.com/css-textshadowCrete
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 :)Logical
oki, so just like i said, import css to underline class , so you have both : JS + CSS jsfiddle.net/5u44B/46Avidin
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.Crete
@Logical maybe this is what you are trying to achieve? jsfiddle.net/webtiki/nJeJh/5Crete
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? :)Logical
@Logical 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!Crete
@Logical I din't mention it but if I were you I would accept this answer as I am shure it fits your need better.Crete
This is exactly how I'd do it in print. See Outline effect to text for a discussion.Caren
C
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);
    });
});

Crete answered 7/4, 2014 at 13:44 Comment(15)
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...Logical
@Logical 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 : https://mcmap.net/q/604589/-margin-top-in-inline-element 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.Crete
@Logical you can use the :after pseudo element to create the underline although it looses all the "semantic" of underlining for SEO --> jsfiddle.net/webtiki/nJeJh/3Crete
@Logical With this technique, you won't loose the SEO semantics for <h1> 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 <h1> tags.Crete
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!Logical
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: jsfiddle.net/ytR8sLogical
@Logical , you need to encode htmlentities : see : .html(encodedStr).text()Avidin
@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.Logical
@Logical 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.Crete
hello, well i just did this only for & jsfiddle.net/ytR8s/4 . very nice question indeed :)Avidin
@GCyrillus oh yes, that is much neeter!Crete
@Crete 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 onceAvidin
@Crete i do not follow you, it only search for the string . i must be missing something here :)Avidin
let us continue this discussion in chatCrete
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!Logical
I
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.

Ideality answered 4/1, 2016 at 16:54 Comment(0)
C
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!

Cloistral answered 2/5, 2014 at 14:8 Comment(4)
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 :pAvidin
oh! sorry about that @GCyrillus. Completely missed that.Cloistral
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. :)Avidin
By the way , thanks for sharing earlier this link medium.com/designing-medium/7c03a9274f9, you should add it too to your answer. It tells lots of things :)Avidin
M
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;}
Malkin answered 4/4, 2014 at 15:9 Comment(5)
why is this downvoted? This answers the question (pretty much the only valid answer, for that matter).Sherrisherrie
It would be more efficient to wrap letters that should not be underlined I do believe as well.Micromillimeter
Yea, in hindsight, wrapping the non-underlined letters would be more efficient, but either would work.Malkin
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 { ... }Micromillimeter
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 questionLie
E
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;
}
Evanescent answered 1/6, 2016 at 10:56 Comment(0)
I
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>
Immure answered 20/9, 2019 at 2:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.