Make middle of three elements in row fill remaining space - html

I need three elements. Two elements on either side, and one text element in the middle. The text in the middle needs to be left-aligned (floating) to the first element.
I need the text to truncate with ellipsis when the page is shrunk. But after specifying overflow styles, when the page is shrunk smaller than the width of the three combined they start moving to new positions and moving out of the parent container.
## This is sample text! ## would turn into ## This is samp... ## (where ## are the side elements) if the width could not accomodate all of the elements.
.container {
height: 30px;
background-color: #ff0000;
}
.container > .container-first {
display: inline-block;
background-color: #0000ff;
width: 20px;
height: 30px;
float: left;
}
.container > .container-second {
display: inline-block;
line-height: 30px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
float: left;
}
.container > .container-third {
display: inline-block;
background-color: #00ff00;
width: 20px;
height: 30px;
float: right;
}
<div class="container">
<div class="container-first"></div>
<div class="container-second">This one has sample text!</div>
<div class="container-third"></div>
</div>
Note that this answer did not help because it just moves each child to its own line.

I am using a flexbox for the .container and set flex: 1 for .container-second. This way all floats can be removed and the document flow stays intact.
Hope this helps.
.container {
height: 30px;
background-color: #ff0000;
display: flex;
}
.container>.container-second {
flex: 1;
}
.container>.container-first {
display: inline-block;
background-color: #0000ff;
width: 20px;
height: 30px;
}
.container>.container-second {
display: inline-block;
line-height: 30px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.container>.container-third {
display: inline-block;
background-color: #00ff00;
width: 20px;
height: 30px;
}
<div class="container">
<div class="container-first"></div>
<div class="container-second">This one has sample text!This one has sample text!This one has sample text!This one has sample text!This one has sample text!</div>
<div class="container-third"></div>
</div>

This can done easily by using bootstap grid and CSS overflow and text-overflow property.
You need to link bootstrap file in head section .
Check this out.
.ellipsis {
text-align: left;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
<div class="container-fluid">
<div class="row">
<div class="col-md-4 col-xs-3">
<div>Hello Hello</div>
</div>
<div class="col-md-4 col-xs-6">
<div class="ellipsis">Hello Hello Hello Hello Hello Hello </div>
</div>
<div class="col-md-4 col-xs-3">
<div>Hello Hello</div>
</div>
</div>
</div>

Related

CSS prevent DIV from wrapping when using text-overflow: ellipsis

I'm trying to fit some text and divs all into a single line (without wrapping) and using text-overflow: ellipsis. However in all my experimenting (I can't even recall all the things I've tried), the text fills up the entire line, and the divs get pushed down onto a new line.
I'd like the text to truncate so the blue boxes are on the same line as the text.
I'm able to get it to work with JS, but I want a pure CSS solution.
EDIT:
Sorry, I should have added some more details.
The text length is variable
The solution should allow for a responsive page design (I put the width: 400px to constrain the container, but in reality it's responsive, sorry I know my question was misleading.)
.page-container{
width: 400px;
background: yellow;
}
div.header {
white-space: nowrap;
display: inline;
width: 100%;
}
div.one-line-div {
font-size: larger;
white-space: nowrap;
width: 100%;
text-overflow: ellipsis;
display: inline-block;
overflow: hidden;
}
.move-divs {
display: inline-block;
float: right;
}
.div1, .div2, .div3, .div4 {
float: right;
margin-right: 12px;
cursor: pointer;
display: inline-block;
width: 30px;
height: 30px;
background: blue;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet"/>
<body>
<div class="page">
<div class="page-container">
<div class="header">
<div class="one-line-div">Text text, so much text here, what do we do with all this text?.
<div class="more-divs">
<div class="div1">
</div>
<div class="div2">
</div>
<div class="div3">
</div>
<div class="div4">
</div>
</div>
</div>
</div>
</div>
</div>
</body>
Have you tried flex-box? Based on what I've tested it should work for you. You'll need to wrap your text in another div, though. And also need to change some things from inline-block back to block, etc. Basically flex-box is the new layout engine that allows you to do some awesome stuff. Generally you shouldn't ever need float if you use flex-box. Check out this guide on flex-box from CSS-Tricks. You can do some amazing things with it. Let me know if you have any questions regarding my answer. I didn't want to go into too much specifics because that'd be a pretty big rabbit hole.
.page-container{
width: 400px;
background: yellow;
}
/*
You don't need this anymore with flex.
div.header {
white-space: nowrap;
display: inline;
width: 100%;
}*/
/* Updated to use flex box. */
div.one-line-div {
display: flex;
flex-direction: row;
font-size: larger;
}
/* define the style for our .text element */
.text {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
/* our .move-divs needs to be flex too */
.more-divs {
display: flex;
flex-direction: row;
}
/* I removed the floats and display inline, since you don't need them */
.div1, .div2, .div3, .div4 {
margin-right: 12px;
cursor: pointer;
width: 30px;
height: 30px;
background: blue;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet"/>
<body>
<div class="page">
<div class="page-container">
<div class="header">
<div class="one-line-div">
<div class="text">
Text text, so much text here, what do we do with all this text?.
</div>
<div class="more-divs">
<div class="div1">
</div>
<div class="div2">
</div>
<div class="div3">
</div>
<div class="div4">
</div>
</div>
</div>
</div>
</div>
</div>
</body>
The solution: put the text in a "span" element . then do the following styles
.page-container{
width: 400px;
background: yellow;
}
div.header {
white-space: nowrap;
display: inline;
width: 100%;
}
div.one-line-div {
font-size: larger;
white-space: nowrap;
width: 100%;
text-overflow: ellipsis;
display: inline-block;
overflow: hidden;
}
.move-divs {
display: inline-block;
float: right;
}
.div1, .div2, .div3, .div4 {
float: right;
margin-right: 12px;
cursor: pointer;
display: inline-block;
width: 30px;
height: 30px;
background: blue;
}
.myText {
max-width: 55%;
text-overflow: ellipsis;
overflow: hidden;
display: inline-block;
}
.more-divs {
display: inline-block
}
<div class="page">
<div class="page-container">
<div class="header">
<div class="one-line-div">
<span class="myText">Text text, so much text here, what do we do with all this
text?.</span>
<div class="more-divs"">
<div class="div1">
</div>
<div class="div2">
</div>
<div class="div3">
</div>
<div class="div4">
</div>
</div>
</div>
</div>
</div>
It is easy and best using flex or grid , though here using float as you said.
When using float this display:inline-block is not needed because float it self makes elements display inline
.page{
background: yellow;
}
.page-container{
width: 400px;
}
div.header {
white-space: nowrap;
width: 100%;
}
div.one-line-div {
font-size: larger;
white-space: nowrap;
width: 100%;
text-overflow: ellipsis;
overflow: hidden;
float: left;
}
.move-divs {
float: right;
}
.div1, .div2, .div3, .div4 {
margin-right: 12px;
cursor: pointer;
display: inline-block;
width: 30px;
height: 30px;
background: blue;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet" />
<body>
<div class="page">
<div class="page-container">
<div class="header">
<div class="one-line-div">Text text, so much text here, what do we do with all this text?.</div>
<div class="more-divs">
<div class="div1">
</div>
<div class="div2">
</div>
<div class="div3">
</div>
<div class="div4">
</div>
</div>
</div>
</div>
</div>
</div>
</body>

Make div not expand parent

I searched for this problem for quite a while now, but only found solutions to the opposite problem.
So here is my problem:
I have a side panel that should be only as wide as its content. This panel has a header with a potentially long title. That header should not expand the panel, but instead be ellipsed.
The HTML looks similar to this
<div class="outer">
<div class="inner">
<div class="header">
superlongtextthatshouldbeellipsed
</div>
<div class="line">
short text
</div>
<div class="line">
even shorter text
</div>
</div>
</div>
This is the CSS to demonstrate the problem
.outer {
background-color: #FFAAAA;
display: flex;
flex-direction: row;
}
.inner {
background-color: #AAAAFF;
display: flex;
flex-direction: column;
margin: 5px;
}
.header {
margin: 5px;
background-color: #AAFFAA;
white-space: nowrap;
overflow: none;
text-overflow: ellipsis;
}
.line {
margin: 5px;
background-color: #FFAAFF;
}
https://jsfiddle.net/1yn725hy/9/
In the fiddle the blue box should be as wide as the second purple box (+margin). The text in the green box should be ellipsed.
How do I do this?
EDIT: Just to clarify: The blue box should fit the content of the purple box which has a varying size. A fixed width does not solve the problem.
First of all your container has to have max-width or width fixed. Second of all your overflow has to be hidden instead of none:
.outer {
background-color: #FFAAAA;
display: flex;
flex-direction: row;
}
.inner {
background-color: #AAAAFF;
display: flex;
flex-direction: column;
margin: 5px;
}
.header {
margin: 5px;
background-color: #AAFFAA;
white-space: nowrap;
max-width:200px;
overflow: hidden;
text-overflow: ellipsis;
}
.line {
margin: 5px;
background-color: #FFAAFF;
}
<div class="outer">
<div class="inner">
<div class="header">
superlongtextthatshouldbeellipsed
</div>
<div class="line">
short text
</div>
<div class="line">
even shorter text
</div>
</div>
</div>
Ok, finally solved it myself. The trick is to use the almighty flexbox and wrap the header in it:
.outer {
background-color: #FFAAAA;
display: flex;
flex-direction: row;
}
.inner {
background-color: #AAAAFF;
display: flex;
flex-direction: column;
margin: 5px;
}
.header {
margin: 5px;
background-color: #AAFFAA;
display: flex;
}
.header2 {
width: 0px;
flex-grow: 1;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.line {
margin: 5px;
background-color: #FFAAFF;
}
<div class="outer">
<div class="inner">
<div class="header">
<div class="header2">
superlongtextthatshouldbeellipsed
</div>
</div>
<div class="line">
short text
</div>
<div class="line">
even shorter text
</div>
</div>
</div>
You should add some width to your div. Otherwise the header text wont ellipsed, because there is no "end".
https://jsfiddle.net/1yn725hy/14/

CSS to create a div that takes remaining width of parent when the other sibling div is as wide as it's content?

How do I go about creating the next layout :
Two divs share the width of a common parent. both of them display text content in a single line, while -
The div on the right is as wide as it's text content
The div on the left takes up all the remaining width of the parent and uses text-overflow: ellipsis to display '...' where the text gets cut.
Here is what I think I know about how it should be implemented -
.parent {
width: 400px;
height: 200px;
}
.left {
display: block;
white-space: nowrap;
text-overflow: ellipsis;
overflow: none;
}
.right {
display: inline-block;
}
<div class='parant'>
<div class='left'> This div should display all text content possible without line-breaking and display '...' where its being cut </div>
<div class='right'> This div is as wide as its text content </div>
</div>
It should look like this example
You can use Flexbox for this, just set display: flex on parent and flex-shrink: 0 on right element.
.parent {
width: 400px;
height: 200px;
display: flex;
}
.left {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
background: red;
}
.right {
background: lightblue;
flex-shrink: 0;
}
<div class='parent'>
<div class='left'> This div should display all text content possible without line-breaking and display '...' where its being cut </div>
<div class='right'> This div is as wide as its text content </div>
</div>
I think it's better using Flexbox for this. You should give display: flex; to .parent and flex:1; to .left. That will do your trick and it will not over flow the parent width also.
.parent {
width: 100%;
height: 200px;
display: flex;
}
.left {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
background: pink;
flex:1;
}
.right {
background: green;
}
<div class='parent'>
<div class='left'> This div should display all text content possible without line-breaking and display '...' where its being cut </div>
<div class='right'> This div is as wide as its text content </div>
</div>
try this
.parent {
width: 300px;
height: 200px;
overflow: hidden;
display: flex;
}
.left {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.right {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
<div class='parent'>
<div class='left'> This div should display all text content possible without line-breaking and display '...' where its being cut </div>
<div class='right'> This div is as wide as its text content </div>
</div>
**
You can use flexbox for your requirement. It is really simple and it will work like any other display properties. You can check this codepen link. This works 100%.
CSS
.container {
display: flex;
max-width: 500px;
border: 1px solid #ddd;
padding: 5px;
}
.one,
.two {
flex-grow: 1;
word-break: break-all;
padding: 10px;
color: #fff;
}
.one {
background-color: red;
}
.two {
background-color: blue;
}

Background of div does not scroll with the contents

I have the following snippet of html that forms an X-Y scrollable listbox
* {
font-family: "consolas";
}
.listbox {
border: 1px solid black;
padding: 4px;
width: 150px;
height: 200px;
display: flex;
flex-direction: column;
}
.caption {
font-weight: bold;
background-color: #aaf;
padding: 10px;
}
.content {
flex-grow: 1;
overflow: scroll;
}
.item {
background-color: #ddd;
padding: 2px;
padding-left: 6px;
margin-top: 4px;
white-space: nowrap;
}
<div class="listbox">
<div class="caption">Caption</div>
<div class="content">
<div class="item">One</div>
<div class="item">Two</div>
<div class="item">Three (this has a longer bit)</div>
<div class="item">Four</div>
<div class="item">Five</div>
<div class="item">Six</div>
<div class="item">Seven</div>
<div class="item">Eight (so does this)</div>
<div class="item">Nine</div>
<div class="item">Ten</div>
</div>
</div>
It's working fine, with one problem, as the user scrolls from left to right, the background of the div seems to get left behind. It's as though the actual div only stretches the width of its parent, and the scrolling/overflow thing is "faked" somehow.
Why is this the case?
How do I address the problem? The behaviour I want is for all the items to appear to be the same width as the largest one.
Try adding a container <div class="items"> around the items set it to display:inline-block.
.items {
display: inline-block;
}
* {
font-family: "consolas";
}
.listbox {
border: 1px solid black;
padding: 4px;
width: 150px;
height: 200px;
display: flex;
flex-direction: column;
}
.caption {
font-weight: bold;
background-color: #aaf;
padding: 10px;
}
.content {
flex-grow: 1;
overflow: scroll;
}
.items {
display: inline-block;
}
.item {
background-color: #ddd;
padding: 2px;
padding-left: 6px;
margin-top: 4px;
white-space: nowrap;
}
<div class="listbox">
<div class="caption">Caption</div>
<div class="content">
<div class="items">
<div class="item">One</div>
<div class="item">Two</div>
<div class="item">Three (this has a longer bit)</div>
<div class="item">Four</div>
<div class="item">Five</div>
<div class="item">Six</div>
<div class="item">Seven</div>
<div class="item">Eight (so does this)</div>
<div class="item">Nine</div>
<div class="item">Ten</div>
</div>
</div>
</div>
Explanation: by default a block level element takes 100% width of the container no more than that, however an inline block will expand to content length if available e.g. in a scrollable container.
Also apply .items {min-width: 100%;} in case you want the background to grow full width even with less text in every row.

how to apply vertical-align: middle at div

I've searched it at online and found some solution. But, nothing works at my project. At most of the solution, I've found:
<div class="a">
<div class="b">
Unknown stuff to be centered.
</div>
</div>
.a {
display: table;
width: 100%;
}
.b {
display: table-cell;
text-align: center;
vertical-align: middle;
}
By applying this technique, I've tried to build something like this: http://jsfiddle.net/L2GZx/1/
The text of left column only needed to be aligned middle vertically. But, it's not working with that technique:
<div class="row">
<div class="left">
<p>Sample Text</p>
</div>
<div class="right">
<p>Text</p>
<p>Input Element</p>
<p>Table</p>
<p>Image</p>
</div>
</div>
<div class="row">
<div class="left">
<p>Sample Text Sample Text Sample Text Sample Text Sample Text </p>
</div>
<div class="right">
<p>Text</p>
<p>Input Element</p>
<p>Table</p>
<p>Image</p>
</div>
</div>
<div class="row">
<div class="left">
<p>Sample Text</p>
</div>
<div class="right">
<p>Text</p>
<p>Input Element</p>
<p>Table</p>
<p>Image</p>
</div>
</div>
CSS:
.row {
width: 100%;
background: #ccc;
border-bottom: 1px solid #999;
display: table;
}
.left {
float: left;
width: 40%;
padding: 20px;
display: table-cell;
vertical-align: middle;
}
.right {
float: right;
background: #fff;
width: 40%;
padding: 20px;
}
How can I make the text of left-column aligned middle vertically? Note: I can't use any fixed height as content of each row will be different
Remove the floats. Floated elements can not also be displayed as table-cells. See updated Fiddle.
.row {
width: 100%;
background: #ccc;
border-bottom: 1px solid #999;
display: table;
}
.left {
width: 40%;
padding: 20px;
display: table-cell;
vertical-align: middle;
}
.right {
display: table-cell;
background: #fff;
width: 40%;
padding: 20px;
}
.left {
width: 40%;
padding: 20px;
display: table-cell;
vertical-align: middle;
}
removing" float:left " from .left style solves that issue, but using table and div together is not that good.Working Example
An alternative that I prefer in a situation like this is:
To not use display: table-cell, but rather use display:
inline-block.
To then use vertical-align: middle on the element.
Sample (revised) markup / css:
<div class="row">
<div class="left">
<p>Sample Text</p>
</div>
<div class="right">
<p>Text</p>
<p>Input Element</p>
<p>Table</p>
<p>Image</p>
</div>
</div>
CSS:
.row {
width: 100%;
background: #ccc;
border-bottom: 1px solid #999;
}
.row > div {
display: inline-block;
/* below 2 lines are IE7 hack to make inline-block work */
zoom: 1;
*display: inline;
/* below is consolidated css for both left / right divs */
width: 40%;
padding: 20px;
}
.left {
vertical-align: middle; /* or top or bottom */
}
.right {
background: #fff;
vertical-align: top; /* or middle or bottom */
}
All you have to do is to add a line-height to the left column and it will be automatically aligned (without vertical-align so you can remove it).
Here it is:
.left {
float: left;
width: 40%;
padding: 20px;
display: table-cell;
line-height:150px;
}
And here is your updated FIDDLE
Using your first example, try something like this. I'll explain how it works in the CSS.
<div class="a">
<div class="b">
Unknown stuff to be centered.
</div>
</div>
.a {
width: 100%;
position: relative; /* We want our parent div to be the basis of our absolute positioned child div */
/* You can set your height here to whatever you want */
}
.b {
position: absolute;
width: 100%; /* Set to be the full width, so that our text is aligned centered */
text-align: center;
top: 50%; /* Positions the top of the div at 50% of the parent height */
left: 0; /* Assures that the child div will be left-most aligned */
margin-top: -.5em; /* Moves the top of our div up by half of the set font size */
height: 1em; /* Sets our height to the height of the desired font */
}
Here is the JSFiddle link to see a live example: http://jsfiddle.net/L2GZx/20/
This is one of the best solutions to absolutely center text inside of a webpage. It does have it's limitations however seeing how it won't react to other elements inside the same parent and it also has to have a set height. So multiline text will have it's shortcomings with this method.
I hope this helps!