Cross-browser CSS text-overflow with floating elements and fluid text width - css

The scenario I have here: http://jsfiddle.net/b2xLgkqu/4/ (approximate minimal reproduction of my actual usage scenario)
Basically, I have a base element with width: 100% which has three children - leftside segment, rightside segment and main text. The left and right side have a known width in rems, but it's completely fluid otherwise. The text-overflow works nicely in Chrome, IE11 and Chrome for Android, but not on the latest Firefox. I'm looking for something that would make it work there too, without breaking any of the other browsers. (I also can't use workarounds like hiding the main text with a background-color on the side elements due to the containing element having semitransparent background color, and I'd like to keep it that way.)
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
.head {
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
position: relative;
}
.left, .right {
width: 5rem;
padding: 0 0.1rem;
position: relative;
z-index: 1;
}
.left {
float: left;
}
.right {
float: right;
}
span {
position: relative;
z-index: 0;
}
<div class="head">
<div class="left">FOO BAR</div>
<div class="right">FOO BAR</div>
<span>
long text
<span style="color: red">that</span>
should end up
<b>wrapping with</b>
text overflow ellipsis blah blah more blogging here
</span>
</div>

You set some styles to .head but you should set them to .head > span instead:
.head > span {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.left, .right {
width: 5rem;
padding: 0 0.1rem;
}
.left {
float: left;
}
.right {
float: right;
}
.head > span {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
<div class="head">
<div class="left">FOO BAR</div>
<div class="right">FOO BAR</div>
<span>
long text
<span style="color: red">that</span>
should end up
<b>wrapping with</b>
text overflow ellipsis blah blah more blogging here
</span>
</div>
Also note it needs display: block in order to interact like you want with the floating elements.

Related

Vertically align two paragraphs on one line, one in center one on right [duplicate]

This question already has answers here:
Center one and right/left align other flexbox element
(11 answers)
Closed 3 years ago.
according to W3Schools
The align attribute is not supported in HTML5. Use CSS instead.
I am wondering how on earth, can I simply align two paragraphs within one line.
I am open to flex box solutions, but, I do not need a third dummy paragraph to behave as a starting point. Also, producing a row and columns seems to overcomplicating this ?simple? task?
This is what I have come up with so far, thus text-align does nothing...:
p {
display: inline-block;
}
.center {
text-align: center;
}
.right {
text-align: right;
}
<div class="container">
<p class="center">Center</p>
<p class="right">Right</p>
</div>
You can do it with the Flexbox and position property:
.container {
position: relative; /* needs to be on the parent */
display: flex; /* displays flex-items (children) inline */
justify-content: center; /* centers them horizontally */
align-items: center; /* and vertically */
}
.container > .right {
position: absolute; /* needs to be on the child */
right: 0;
}
#media (max-width: 480px) { /* adjust */
.container {
flex-direction: column; /* stacks flex-items vertically */
}
.container > .right {
position: static; /* back to default */
align-self: flex-end; /* aligns to the horizontal end */
}
}
<div class="container">
<p class="center">Center</p>
<p class="right">Right</p>
</div>
p {
display: inline-block;
}
.center {
margin-left:50%;
}
.right {
float: right;
}
If I understood your question. You should add some percentage width to your two paragraphs and then add float:right; to both of them. Also, don't forget to keep the .right paragraph above the .center paragraph in your html.
See the below snippet for reference.
p {
display: inline-block;
}
.center {
text-align: center;
width: 33.3333%;
float: right;
}
.right {
text-align: right;
width: 33.33333%;
float: right;
}
<div class="container">
<p class="right">Right</p>
<p class="center">Center</p>
</div>
Hope this help.
With the litlle description you gave, there is little to answer.
to start:
With flex I would do :
.container {
display:flex;
}
.center {
flex:1;
text-align: center;
}
.right {
text-align: right;
}
<div class="container">
<p class="center">Center</p>
<p class="right">Right</p>
</div>
With the table-layout (IE8 & +) , I would do
.container {
display: table;
width: 100%;
}
p {
display: table-cell;
}
.center {
text-align: center;/* will use whole space avalaible*/
}
.right {
text-align: right;
width: 5em;/* a small value to shrink it on its content */
}
<div class="container">
<p class="center">Center</p>
<p class="right">Right</p>
</div>
with grid, I would do
.container {
display:grid;
grid-template-columns:1fr auto;
}
.center {
text-align: center;
}
.right {
text-align: right;
}
<div class="container">
<p class="center">Center</p>
<p class="right">Right</p>
</div
I would not use float nor inline-block where elements can wrap to the next line any time (unless max-width is set for both elements) ;)
One simple solution:
.container {
position: relative;
text-align: center;
}
.center {
display: inline-block;
}
.right {
display: inline-block;
position: absolute;
top: 0;
right: 0;
}
With position: absolute applied on .right, you can move the paragraph wherever you want within the next parent element that has position: relative (If no parent has position set, the element will relate to the window).
The reason why text-align is not working in your case, is because of display: inline-block.
Some basics you need to know:
A paragraph element is just a form of a container. The text in it is basically another element itself.
text-align aligns the content within an element. Hence, the text gets aligned to the borders of the paragraph element.
The default value for a paragraph element is display: block. That means its width spans over the entire width of its parent element (or the window in case no container is declared). Hence, text-align will have a visible effect.
display: inline-block will make the borders of the element it is applied on shrink to the size of its content. Since text-align affects the content, not the element itself, your paragraph element won't move.
.container {
display:grid;
}
p {
display: inline-block;
}
.center {
text-align: center;
}
.right {
text-align: right;
}
.left {
text-align: left;
}
<div class="container">
<p class="center">Center</p>
<br>
<p class="right">Right</p>
<br>
<p class="left">Left</p>
</div>

Keeping an :after element on ellipsis

I want to have an icon (checkmark) behind a line with variable width.
if the line becomes too long, i want it to be truncated with ellipsis.
But the checkmark is supposed to stay AFTER the ellipsis
https://jsfiddle.net/Lkvt39re/
.inner {
width: 80%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
i've set the width to 80%, and want to have the :afterinserted ..well, after the ellipsis.
how can i do that?
Thanks
Try adding a ::before pseudo element instead, then style it to float right. This way, your pseudo content won't become trimmed out by the restrictions set to the element width.
CSS
.inner::before {
content: 'X';
float: right;
}
Alternatively
You can set the ::after pseudo element to the parent element .outer, then set the nested .inner element to display inline-block (allowing the pseudo element of .outer to fall after initial width of .inner) with a max-width declared; once this max-width is exceeded your overflow rule will apply, giving you the ellipsis but still keeping the pseudo element of .outer visible after the text-overflow.
The problem is trying to declare this pseudo element to an element that you've also declared width restrictions and overflow rules to. You'll need to declare the pseudo element outside of the element that will, at some point, begin trimming out content.
.inner {
width: 80%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.inner::before {
content: 'X';
float: right;
}
.outer {
width: 200px;
}
/* Alternative */
.alternative .inner {
max-width: 80%;
width: auto;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
}
.alternative .inner.no-max-width {
max-width: none;
}
.alternative .inner::before {
display: none;
}
.alternative.outer::after {
content: 'X';
display: inline-block;
}
<div class="outer">
<div class="inner">
this is pretty longggggg
</div>
</div>
<br>
<p><strong>Alternative</strong></p>
<div class="alternative outer">
<div class="inner">
this is pretty longgggggggggggg
</div>
</div>
<div class="alternative outer">
<div class="inner no-max-width">
this is pretty long
</div>
</div>
Devman,
You need to give the pseudo element some shape and define it as either an inline-block or a block element to do so. You can then set the dimensions appropriate to your styling.
Check out this edit:
.inner {
width: 80%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
position:relative;
/** give your container some extra space for the pseudo **/
padding-right: 25px;
}
.inner::after {
content: 'X';
color:red;
/** define it as a "block" element and add dimension **/
display: inline-block;
height: 1.0rem;
width: 1.0rem;
}
.outer {
width: 180px;
}
http://codepen.io/jonrandahl/pen/rLMKwR

CSS pseudo after underline with floats

I have an underline for headings created with pseudo :after elements, when this heading is displayed to the right of a floated image/div, the underline is shifted over the image/div.
h2:after {
content: '';
position: relative;
max-width: 100px;
display: block;
height: 4px;
background: #0073ae;
}
Here's a short codepen explaining it: http://codepen.io/costelc/pen/GqgdvB
Any idea is appreciated. Thanks
Floats are out-of-flow, so this is expected. If you don't want the header to overlap the float, you should establish a block formatting context.
A common way is setting overflow to anything but visible, e.g.
h2 {
overflow: hidden;
}
From CSS 2.1 Floats,
Since a float is not in the flow, non-positioned block boxes created
before and after the float box flow vertically as if the float did not
exist.
The border box of a table, a block-level replaced element, or an
element in the normal flow that establishes a new block formatting
context (such as an element with overflow other than visible)
must not overlap the margin box of any floats in the same block
formatting context as the element itself
body {
max-width: 300px;
}
.right {
width: 100px;
height: 100px;
background: #eee;
float: right;
margin: 0 0 0 20px;
}
.clear {
clear: both;
}
.left {
width: 100px;
height: 100px;
background: #eee;
float: left;
margin: 0 20px 0 0;
}
h2 {
overflow: hidden;
}
h2:after {
content: '';
position: relative;
max-width: 100px;
display: block;
height: 4px;
background: #0073ae;
}
<h2>Good heading here</h2>
<div class="right"></div>
<h2>Another good heading here</h2>
<p>anything here</p>
<br class="clear">
<div class="left"></div>
<h2>Bad heading here</h2>
<p>anything here</p>

Text overflow hides text when it shouldn't in Safari

I want to have various tags in a container and have them display ellipsis when the tag text is too big (i.e. when it would stretch beyond the width of the container). The problem I am facing is that in Safari, the ellipsis are displayed even though the tag has space to display the full content.
This is the code that shows what I'm trying to achieve:
.tag {
height: 30px;
background: #F67;
line-height: 30px;
display: block;
float: left;
max-width: calc(100% - 20px);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
padding: 0 5px;
margin: 5px 5px 0;
border-radius: 16px;
}
.content {
float: left;
max-width: calc(100% - 20px);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.icon {
float: right;
background: blue;
width: 20px;
text-align: center;
color: white;
text-decoration: none;
}
.container {
border: 2px solid blue;
width: 300px;
height: 400px;
padding: 10px;
}
<div class="container">
<div class="tag">
<span class="content">Some tag</span>
X
</div>
<div class="tag">
<span class="content">Some tag</span>
X
</div>
<span class="tag">
blahbsalkfnewijfnewifbwiefnbijfneifjnweifniwjenfewi
</span>
<div class="tag">
<span class="content">Some tags</span>
X
</div>
</div>
If you're running the snippet above in Safari(v8.0.8 is the one I am using) you can see the last tag shows ellipsis even though it still has space to stretch and display the full text. If you can't see what I am talking about here is a screenshot of the issue:
text-overflow problem on safari image
Small mention about the 'X' is that it is intended as an icon someone could click on and delete the tag, but that functionality is not the subject of this question.
I'm using this trick: adding a non-break space right after the text. You can add it directly into your html, like <div class="ellipsis">Test </div> or you can use the :after pseudo element. Here's the .ellipsis class that I'm using:
.ellipsis {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.ellipsis:after {
content: "\0000a0";
display: inline-block;
width: 0;
}
The use of :after has another advantage, it's hidden by setting width: 0;, so you won't notice a larger gap between this element and the thing next to it (another element or a border).
When you remove the following lines from your .content element it works fine by me.
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
example: http://codepen.io/WartClaes/pen/ZQxaKW?editors=1100
Edit: although when looking further I see that you don't always use the same HTML structure? Which results in the double text overflow declaration. Isn't it possible to always use the same structure?
You need to add a "width" for the text, down to the text-overflow:
width: 100%; /Or the size you need/
It works for me in the safari 13.

Dont wrap row of divs

How to create set of float:right divs one next to another and make them not wrap, no matter how much of them exists or how wide is any of them. If they together are wider than viewport, then x-scroll should appear.
Content inside those divs should wrap normally.
CSS only would be good.
Style the parent element with white-space: nowrap;, though this only works with display: inline (or display: inline-block;) elements. Given the following HTML:
<div id="parent">
<div class="child"></div>
<!-- there's quite a lot of these... -->
<div class="child"></div>
</div>
And the CSS:
#parent {
white-space: nowrap;
}
#parent .child {
display: inline-block;
/* there's some other CSS for aesthetics */
}
JS Fiddle demo.
Unfortunately I don't think there is a way of forcing float-ed elements to not wrap to a new line.
To preserve or, rather, force normal line-wrapping for descendant elements you'll have to explicitly over-ride the inheritance and set white-space: normal (as well as, possibly, define a width or max-width)
/* other CSS remains intact */
#parent .child {
display: inline-block;
/* irrelevant/aesthetic CSS */
white-space: normal;
max-width: 8em;
}
JS Fiddle demo.
Few elements: http://jsfiddle.net/thirtydot/A8duy/
Many elements: http://jsfiddle.net/thirtydot/A8duy/1/
HTML:
<div class="block-container">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
</div>​
CSS:
.block-container {
text-align: right;
white-space: nowrap;
float: left;
width: 100%;
margin-bottom: 1em;
border: 1px solid red;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.block-container > div {
width: 50px;
height: 50px;
vertical-align: top;
display: inline-block;
*display: inline;
zoom: 1;
text-align: left;
white-space: normal;
border: 1px solid blue;
}

Resources