Word wrap with css `hyphens` fails to wrap substring - css

I recently switched from overflow-wrap to hyphens for breaking text between lines. However, I have encountered a case that seemingly fails to hyphenate any words before a certain substring. I am at a loss as to why this could be.
Observe the gif below, the full string to be displayed is /people/type:astronauts/name-gregory-chamitoff/profile however when the width is less than about 210px none of the words in the substring /people/type:astronauts/name- are ever hyphenated and pushed to the next line. But, longer that 210px the hyphenation works fine. It's almost like it's treating this substring as a continuous word.
.test {
font-size: 20px;
width: 210px;
/* adding this works but defeats the use of hyphens
overflow-wrap: break-word;
*/
hyphens: auto;
overflow: hidden;
background-color: white;
}
html {
background-color: black;
}
<div class="test">/people/type:astronauts/name-gregory-chamitoff/profile</div>
The only thing I have found that fixes this is to use something like that below as a catch-all. This is great however, it does not prioritize hyphenating over breaking of the words. I am looking for other solutions than this that makes hyphens work for all or most strings, or even this one case!
.test {
overflow-wrap: break-word;
word-wrap: break-word;
word-break: break-all;
word-break: break-word;
hyphens: auto;
}

As #Salman A has pointed out, quite a lot of characters (e.g like slashes or colons, undescores etc.) are not recognized as proper word/syllable joints. Strings like "chamitoff/profile" will be treated as one long compound word "chamitoffprofile".
When it comes to URL like strings, you don't want to overflow – you'd still be better off with something like word-break: break-word;
Speaking of css hyphens property: its capabilities are still 'limited' (at least in 2021).
E.g. Chrome has introduced support for this feature in version 88 (according to caniuse).
Here's a resizable snippet:
*{
box-sizing:border-box;
}
body{
font-family: 'Segoe UI';
font-size: calc(1.75vw + 1.75vh / 2);
padding: 10px;
}
.resizable{
width: 20ch;
height: 10em;
hyphens: auto;
resize:both;
overflow:auto;
padding-right:1em;
border: 1px solid #ccc
}
.resizable p{
hyphens: auto;
}
.break-words{
hyphens: none;
word-break: break-word;
}
<h2>Example</h2>
<div class="resizable">
<p>people/type:astronauts/name-gregory-chamitoff/profile <br /><strong>Original</strong></p>
<p>peopletype:astronautsname-gregory-chamitoffprofile <br /><strong>Dash replaced by hyphens</strong></p>
<p>peopletype_astronautsname_gregory_chamitoff_profile <br /><strong>Dash replaced by underscores</strong></p>
<p>peopletype astronautsname-gregory-chamitoffprofile <br /><strong>Dash and colons replaced by hyphens</strong></p>
<p>peopletype astronauts name gregory chamitoff profile <br /><strong>Dash replaced by spaces</strong></p>
<p class="break-words">people/type:astronauts/name-gregory-chamitoff/profile <br /><strong>Dash replaced by spaces</strong></p>
</div>
<h2>URLs</h2>
<div class="resizable">
<p>https://www.maybeweshouldhaveoptedfor ashorterdomain.com/contact/specialinterest?product_id=1234567878 <br /><strong>URL – "hyphenated"</strong></p>
<p class="break-words">https://www.maybeweshouldhaveoptedfor ashorterdomain.com/contact/specialinterest?product_id=1234567878 <br /><strong>URL – word-break</strong></p>
<p class="break-words">contact#maybeweshouldhaveoptedfor ashorterdomain.com <br /><strong>Email example</strong></p>
</div>
Unless browsers/css-implementations widely support improved hyphenation concepts like hyphenate-limit-chars (... formerly existent) or hyphenation exception rules you should really curb your enthusiasm.
Conclusion
(2021 – hopefully we'll see improvements the next years)
You still have to choose between an imperfect 'brute-force' method like word-break – at least preventing undesired overflows
and an inelaborate (... to be very polite) css based hyphenation property/feature that's still missing any mandatory fine grained controls.

I am not sure if it is what are you looking for:
.test {
hyphens: auto;
color:white;
}
html {
background-color: black;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="style.css">
</head>
<body >
<div class="test">/people/type:&shyastronauts/&shyname-gregory-chamitoff/profile here i have another words</div>
</body>
</html>

Related

Why hyphens don't work with inner <span>?

I'm trying to get hyphens working on text that has <span> elements inside for highlighting. This seems to break the hyphen algorithm. Is there any way to fix the behaviour so that hyphens are placed the same as without <span> elements?
I'm not asking about a workaround like ­
The Code (sandbox: https://codepen.io/anon/pen/ayzxpM):
.limit {
max-width: 50px;
hyphens: auto;
font-size: 20px;
background-color: #eee;
}
span {
color: red;
}
<div class="limit">
<p>
Appletreefruitthing
</p>
<p>
Apple<span>tree</span>fruitthing
</p>
</div>
Using the lang attribute
Adding the lang attribute as Vadim Ovchinnikov suggested (<div class="limit" lang="en">) can lead better results on some platform/browser combinations. On Firefox 54, Windows 10 this is the result:
But even that seems buggy. The hyphen should be black in my opinon and the hyphen algorithm seems to miss the chance to make a line break between "fruit" and "tree", also completly ignoring the max-width that is set for the container.
Actually, it does work with spans, in a number of browsers. You just used a word that is not recognized. Here's an example with a normal English word, that works in IE (should also work in Edge) and FF on Win7:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1">
<title>Demo</title>
<style>
div {
max-width: 50px;
-webkit-hyphens: auto;
-moz-hyphens: auto;
-ms-hyphens: auto;
hyphens: auto;
font-size: 20px;
background-color: #eee;
}
span {
color: red;
}
</style>
</head>
<body>
<div>
<p>Incomprehensibilities</p>
<p>Incom<span>pre</span>hensibilities</p>
</div>
</body>
</html>
It does not work in Chrome on Win, because that currently (June 2018) still does not support hyphens at all. It also does not work in any iOS browser. So you will have to use soft hyphens after all. But as you stated that you were curious about the mechanism, I thought it worthwhile to still post this answer.
Chrome has only partial support for hyphens property (only Mac and Android platforms), so you can't make it work on Windows.
I don't see any difference between span presence and absence in Firefox, IE and Edge (all on Windows) for this code.
To make it work there you'll need set lang for container and add vendor prefixes (for -ms-hyphens IE/Edge and -webkit-hyphens for Safari). Demo:
.limit {
max-width: 50px;
font-size: 20px;
/* Safari */
-webkit-hyphens: auto;
/* IE, Edge */
-ms-hyphens: auto;
hyphens: auto;
background-color: #eee;
}
span {
color: red;
}
<div class="limit" lang="en">
<p>
Appletreefruitthing
</p>
<p>
Apple<span>tree</span>fruitthing
</p>
</div>
To work in all browsers you may shouldn't use CSS hyphens property, just insert ­ manually where you want hyphens.
.limit {
max-width: 50px;
font-size: 20px;
background-color: #eee;
}
span {
color: red;
}
<div class="limit">
<p>
Apple­tree­fruitthing
</p>
<p>
Apple­<span>tree</span>­fruitthing
</p>
</div>
hyphens: manual
togteher with
­
might work
see documentation here
https://css-tricks.com/almanac/properties/h/hyphenate/
this code on codepen seems to work
<div class="limit">
<p>
Appletreefruitthing
</p>
<p>
Apple­<span>tree</span>­fruit­thing
</p>
</div>
CSS
.limit {
hyphens: manual;
}

Why are my em values inconsistent between elements?

So I'm having an issue with consistent sizing of "em" values and I can't seem to figure out why.
I am using SCSS for my site and preprocessing all my SCSS files to a single CSS file.
Let me illustrate how my structure is set up.
/* Value used for border width
$defaultBorderWidth: $sizeSmallest; */
.test {
width: 5em;
height: 5em;
border-style: solid;
border-width: 0.15em; /* normally $defaultBorderWidth */
}
.test div {
width: 1em;
height: 1em;
border-style: solid;
border-width: 0.15em; /* normally $defaultBorderWidth */
}
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=3.0">
</head>
<body>
<div class="test">
<div></div>
</div>
</body>
</html>
This in turn shows the result I am expecting, which is a 2px border on both div tags. I am able to replicate this on my site in exactly the same way.
My issue is that in some of my widgets, there are instances where I get a 3px border instead of 2px.
I've read that my border-width could be cascading with another attribute value, but for the life of me can't figure out where or why it's happening. When I look at the developer tools in my browsers I see all instances of border-width are 0.15em.
If an explanation / debug cannot be determined, I can provide a live site example, with the expectation that it will be corrected on the live site ( FYI for future viewers of this article ).
since095 provided the answer to use rem as opposed to em. Where rem always uses the root default font size of the <html> tag (which you can override), in contrast em uses the current tag font size and adjusts other em values accordingly (good for inheritance).
There are advantages and disadvantages of both, and it really comes down to how you intend to structure your site. Inheritance can get messy and complicated really fast, but if used correctly can be very powerful. Controlling every aspect of your site with uniform measurements can help streamline and simplify, but doesn't carry the power of inheritance.
I've come across those that suggest a combination of the two, using rem to set constants such as font size, borders, and em for spacing such as margins and padding.
Below is an example of the use of using rem and em.
.testRem h1 {
border-style: solid;
font-size: 3rem;
width: 15rem;
height: 3rem;
margin: 0.5rem;
border-width: 0.5rem;
}
.testEm h1 {
border-style: solid;
font-size: 3em;
width: 5em;
height: 3em;
margin: 0.5em;
border-width: 0.5em;
}
<!doctype html>
<html>
<head>
</head>
<body>
<div class="testRem">
<h1>Test rem</h1>
<div class="testEm">
<h1>Test em</h1>
</div>
</body>
</html>

Why does IE8 ignore a child element's margin?

When I add a margin to .child in the following code IE8 ignores it. In modern browsers the same code is working as expected. What is causing this?
<html lang=“de“ xml:lang=“de“ xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv=“Content-Type“ content=“text/html“; charset=“iso-8859-1“ />
<title></title>
<style>
.parent {
margin: 5px;
border: 10px solid blue;
position: relative;
}
.child {
margin: 10px;
border: 10px solid red;
padding: 4px;
}
</style>
</head>
<body>
<div class="parent">
<p class="child" style="width:80%; position:relative; left:10px; top:10px; background-color:yellow;">I'm the CHILD!
<span id="textOutput"></span>
</p>
</div>
</body>
</html>
The problem is that you have not supplied a doctype which means that IE8 does not know what rendering mode to use and is therefore defaulting to quirks mode. Quirks mode is essential an old, non-standard layout engine used back when the web was young:
There are now three modes used by the layout engines in web browsers: quirks mode, almost standards mode, and full standards mode. In quirks mode, layout emulates nonstandard behavior in Navigator 4 and Internet Explorer 5. This is essential in order to support websites that were built before the widespread adoption of web standards. In full standards mode, the behavior is (hopefully) the behavior described by the HTML and CSS specifications. In almost standards mode, there are only a very small number of quirks implemented.
Quirks Mode and Standards Mode (https://developer.mozilla.org/en-US/docs/Quirks_Mode_and_Standards_Mode)
Browsers handle a lack of doctype in different ways and you should always ensure that you specify one at the beginning of you HTML to ensure consistent rendering of your page. At time of writing I would recommend the HTML5 doctype as it is short, clear and supported as far back as IE6.
<!DOCTYPE html>
<html lang="de" xml:lang="de" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title></title>
<style>
.parent {
margin: 5px;
border: 10px solid blue;
position: relative;
}
.child {
margin: 10px;
border: 10px solid red;
padding: 4px;
}
</style>
</head>
<body>
<div class="parent">
<p class="child" style="width:80%; position:relative; left:10px; top:10px; background-color:yellow;">I'm the CHILD!
<span id="textOutput"></span>
</p>
</div>
</body>
</html>
It should also be noted that you need to use normal quotation marks not curly quotes for your attribute values and need a closing html tag.

CSS Hyphens Not Working in Firefox?

I am attempting to use CSS Hyphens. They work in IE 11 and Safari but does not work in Firefox properly and I am unsure why. Here is an example:
.container{
width: 16.6667%;
background:#ccc;
}
h3{
font-size: 0.95rem;
font-weight: 600;
-moz-hyphens: auto;
-webkit-hyphens: auto;
-ms-hyphens: auto;
hyphens: auto;
}
<div class="container">
<h3>DIAGNOSEVERFAHREN</h3>
</div>
When you run the snippet in Firefox the word DIAGNOSEVERFAHREN overflows the container and does not break. In Safari and IE it breaks like I expect. Why doesn't this work in Firefox?
Edit
As noted by Marat Tanalin's answer one must include the lang attribute for the hyphens to work correctly. I have this as my <html> tag:
<html class="no-js" lang="de">
Make sure the element or some of its parents has an appropriate lang attribute. It is crucial for CSS hyphens to work.
In general, at least the HTML element should have the attribute:
<html lang="en">
For uppercasing characters, use CSS instead of hardcoded uppercased text in HTML:
.example {text-transform: uppercase; }
Uppercased german text is not hyphenated in Firefox 37 and older due to the bug 1105644 fixed in Firefox 38.
For some strange reason it seems to be because the word is in capital letters. I assume it has something to do with Firefox not thinking that it is a word when it searches the hyphenation dictionary.
I couldn't find any bug reports on it but #MaratTanalin thinks that it has been fixed in Firefox v38.
p {
width: 55px;
border: 1px solid black;
-moz-hyphens: auto;
hyphens: auto;
}
<div>
<h4>English</h4>
<p lang="en" class="auto">DIAGNOSEVERFAHREN</p>
<p lang="en" class="auto">Diagnoseverfahren</p>
<p lang="en" class="auto">diagnoseverfahren</p>
</div>
<div>
<h4>German</h4>
<p lang="de" class="auto">DIAGNOSEVERFAHREN</p>
<p lang="de" class="auto">Diagnoseverfahren</p>
</div>
Edit: It affects all capitalized and uppercase words. Apparently this is by design in Firefox and it won't be fixed anytime soon. Only German language supports the feature of hyphenating capitalized (not uppercase) words.
https://bugzilla.mozilla.org/show_bug.cgi?id=656879
I got this type of issue on ios safari , there are multiple hyphens on that page few of those were not working while remaining works . but i am not supposed to use text-transform:uppercase, so increased the font size to 1px and it worked for me.
Inorder to demonstrate the concept of hyphenation, you need to give the lang attribute is set to en on the parent element.

word-break: break-word not working in <select> element Internet explorer 10

word-break: break-word working fine in all the other browser including Internet Explorer.
But as soon as you add it into a <SELECT></SELECT> element.
Here is a sample that works in all browsers except IE.
<!DOCTYPE html>
<html>
<head>
<style>
p.test, select
{
width:100px;
border:1px solid #000000;
-ms-word-break: break-all; /* wraps the text in the selector so it prints properly*/
word-break: break-all;
/* Non standard for webkit */
word-break: break-word;
-webkit-hyphens: auto;
-moz-hyphens: auto;
-ms-hyphens: auto;
hyphens: auto;
white-space: pre-wrap;
border: 1px dotted red;
}
</style>
</head>
<body>
<p class="test"> This paragraph contains a very long word: thisisaveryveryveryveryveryverylongword. The long word will break and wrap to the next line.</p>
<select class="test">
<option>testshr1</option>
<option>tb details</option>
<option>This paragraph contains a very long word: thisisaveryveryveryveryveryverylongword.</option>
<option>test</option>
</select>
</body>
</html>
This is a feature in IE: it simply renders each option element on one line. Looking at the situation in Developer Tools, you can see that your settings are recognized (and inherited, when applicable, from select to option). But the rendering of a select element is special, and does not do line breaks.
The conclusion is that you should not create such problems. The select element is meant to be used for relatively short options, and the IE behavior is quite understandable. Either shorten the option texts considerably, or use a different control, like a set of radio buttons.
try following code
<style>
select option{
width:100px;
word-break: break-all;
}
</style>
Try using this:
word-wrap: break-word

Resources