flexbox | flex item being pushed out of containing div (off screen) - css

I'm using the flexbox layout to style a list of past tasks. The task description and the time are always going to be of very variable lengths.
Everything looks great until a task description is entered which is long enough to wrap onto a second line and then the 'time' item (on the far right of the screen) is pushed slightly to the right - off the screen - hiding some of the content.
You can see the short description displays perfectly below, but the long one pushes what should be '00:08' off the screen AND the task description moves to the left as well!!
Here's a fiddle for the code (which is below as per Stackoverflow's rules).
If you resize the pane containing the result the '00:08' doesn't fall off the page but it does clearly move too far to the right.
The above screenshot is in Chrome or Safari (the two browsers I was using) when shrinking the width of the window until the description wraps onto a second line.
I would like everything to display as per the first (short description) line if possible! And also to understand why this is behaving as it currently is.
P.S. I have tried using floats and also using a table display layout but both of these techniques caused quite a few bugs, mostly because of the variable length content (so please don't suggest these as alternatives :)).
ul {
margin:0;
padding: 0;
}
#tasklist{
width: 100%;
}
.task-one-line{
display: flex;
flex-direction:row;
flex-wrap: nowrap;
justify-content: space-between;
align-item: baseline; /*flex-end*/
display: -webkit-flex;
-webkit-flex-direction:row;
-webkit-flex-wrap: nowrap;
-webkit-justify-content: space-between;
-webkit-align-item: baseline;
border-bottom: 1px solid #d3d3d3;
width: 100%;
}
.task-one-line i{
width:1.5em;
padding: 0.5em 0.3em 0.5em 0.3em;
/*border: 1px solid green;*/
}
span.task-desc{
flex-grow: 5;
-webkit-flex-grow: 5;
text-align:left;
padding: 0.3em 0.4em 0.3em 0.4em;
/*border: 1px solid red;*/
}
span.task-time{
flex-grow: 1;
-webkit-flex-grow: 1;
flex-basis:4em;
-webkit-flex-basis:4em;
text-align:right;
padding: 0.3em 0.5em 0.3em 0.5em;
/*border: 1px solid blue ;*/
}
<ul id="tasklist">
<li class="task-one-line">
<i class="fa fa-check-circle-o"></i>
<span class="task-desc">And a short one</span>
<span class="task-time">00:01</span>
</li>
<li class="task-one-line">
<i class="fa fa-check-circle-o"></i>
<span class="task-desc">Here's a super long long long long long long description that might wrap onto another line</span>
<span class="task-time">00:08</span>
</li>
</ul>

I had a similar issue, I created a pen with the fix:
https://codepen.io/anon/pen/vRBMMm
.flex {
display: flex;
padding: 8px;
border: 1px solid;
}
.a {
margin-right: 16px;
}
.b {
flex: 1;
background: #ffbaba;
min-width: 0;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.c {
flex-shrink: 0;
margin-left: 16px;
}
<div class="flex">
<div class="a">1st div</div>
<div class="b">HELLO2HELLO2 HELLO2HELLO2 2222 HELLO2HELLO 22222</div>
<div class="c">3rd div</div>
</div>

Really, you only want the text content to have a flexible width (the time and the icon should have a fixed width and not shrink). This could be pretty easily accomplished with tables, absolute positioning, or flexbox.
Here's the flexbox that you need to know:
.task-time: flex: 1 0 4em
.task-one-line i.fa { flex: 0 0 auto; }
ul {
margin:0;
padding: 0;
}
#tasklist{
width: 100%;
}
.task-one-line i.fa { flex: 0 0 auto; }
.task-one-line{
display: flex;
flex-direction:row;
flex-wrap: nowrap;
justify-content: space-between;
align-item: baseline; /*flex-end*/
display: -webkit-flex;
-webkit-flex-direction:row;
-webkit-flex-wrap: nowrap;
-webkit-justify-content: space-between;
-webkit-align-item: baseline;
border-bottom: 1px solid #d3d3d3;
width: 100%;
}
.task-one-line i{
width:1.5em;
padding: 0.5em 0.3em 0.5em 0.3em;
/*border: 1px solid green;*/
}
span.task-desc{
flex-grow: 5;
-webkit-flex-grow: 5;
text-align:left;
padding: 0.3em 0.4em 0.3em 0.4em;
/*border: 1px solid red;*/
}
span.task-time{
flex: 1 0 4em;
-webkit-flex: 1 0 4em;
text-align:right;
padding: 0.3em 0.5em 0.3em 0.5em;
/*border: 1px solid blue ;*/
}
<ul id="tasklist">
<li class="task-one-line">
<i class="fa fa-check-circle-o"></i>
<span class="task-desc">And a short one</span>
<span class="task-time">00:01</span>
</li>
<li class="task-one-line">
<i class="fa fa-check-circle-o"></i>
<span class="task-desc">Here's a super long long long long long long description that might wrap onto another line long long long long long long description that might wrap onto another line</span>
<span class="task-time">00:08</span>
</li>
</ul>

My general rule for flex is flex the containers you want to flex and don't flex the ones you do not. I would do the following to the time container.
span.task-time {flex: none;}

Related

CSS dynamically determine number of columns based on max-content of children

I'm trying to use css columns to display a dynamic number of columns based on the maximum width needed for the children to display nicely (such that the text doesn't wrap onto a new line where possible). I'd then like to stretch each element to fit the available space in the column.
This is what I have (Here is a JSFiddle):
But this is what I'd like to see (all elements have equal width):
This is the code I've tried:
<div class="columns">
<div>
Lorem
</div>
<div>
Ipsum
</div>
<div>
Dollar
</div>
<div>
Euro
</div>
<div>
Bitcoin
</div>
</div>
* {
padding: 0;
margin: 0;
}
.columns {
columns: auto;
column-gap: 1rem;
background: #4cafff;
padding: 1rem 0;
}
.columns > div {
width: max-content;
background: #4caf50;
color: white;
font-size: 2rem;
border: 2px solid green;
margin: 1rem;
}
max-content is not work like that. It is make the content not to wrap. I mean, width or height of content will be maximum size of your content. It will be fit.
If you want to equal width of all element, you can use specific pixel for width.
Like this:
.columns > div {
width: 95px;
text-align: center;
background: #4caf50;
color: white;
font-size: 2rem;
border: 2px solid green;
margin: 1rem;
}
Try this CSS
* {
padding: 0;
margin: 0;
}
.columns {
display: flex;
flex-wrap: wrap;
background: #4cafff;
padding: 1rem 0;
}
.columns > div {
background: #4caf50;
flex: 1;
color: white;
font-size: 2rem;
border: 2px solid green;
margin: 1rem;
}

text background new line padding issue

I am dealing with text blocks (background blocks over text) and face some issues with paddings on new line. The problem occurs when the browser(e.g. mobile) cuts the text into to two lines due to lack of width. text then looks like this:
I don't really know how to set a padding css on the end of the new lines, since it could break up anywhere of the sentence. You could say put a span on it with padding, but it is not fixed where the line will break down. It depends on the width. Any recommendations?
You could apply display: inline-block but that will turn the background color into an ugly box which doesn't look as nice as having an exact width background for each line. Unfortunately CSS doesn't let us target individual lines except for the first one.
If you don't mind getting a little "creative" (or hacky) you could wrap each word in its own element in the backend or using JavaScript and apply the background color to those elements. Adjust the parent's word-spacing accordingly to eliminate gaps.
.main {
font-family: sans-serif;
font-weight: bold;
background-color: #99c;
display: flex;
height: 400px;
flex-direction: row;
align-items: center;
}
.text-container {
max-width: 500px;
display: inline-block;
word-spacing: -15px;
position: relative;
padding-left: 20px;
overflow: hidden;
}
.text-container::before {
content: '';
background-color: black;
position: absolute;
top: 0;
left: 0;
width: 20px;
height: 100%;
z-index: 1;
}
span {
font-size: 36px;
line-height: 1.5em;
color: white;
background-color: black;
padding: 0.25em 0.5em 0.25em 0;
max-width: 360px;
}
<div class="main">
<div class="text-container">
<span>A</span> <span>Movie</span> <span>in</span> <span>the</span> <span>park:</span> <span>Kung</span> <span>Fu</span> <span>Panda</span>
</div>
</div>
You can use box-shadow for this issue and display inline:
<div class="text">
<span class="text-container">A Movie in the park: Kung Fu Panda</span>
</div>
And css:
.text > span {
display: inline;
box-shadow: 25px 0 0 black, -10px 0 0 black;
background-color: black;
color: white;
}
Try to add after "Park:" and before "Kung"
padding workded!!!
change width by console browser and see result:
h1{
background-color: #ff6a6a;
padding: 33px;
display: inline-block;
word-wrap: break-word;
width:300px
}
<h1>rert ert erttttttttttttttt 00000000000000000000 dfgdfgd dfgdfgdft ertert </h1>
Use <p> tag to wrap up the text and it apparently works demo
<div class="main">
<div class="text-container">
<p id="test">A Movie in the park: Kung Fu Panda</p>
</div>
</div>
css
.main {
font-family: sans-serif;
font-weight: bold;
background-color: #99c;
display: flex;
height: 400px;
flex-direction: row;
align-items: center;
}
.text-container {
max-width: 400px;
}
p {
font-size: 36px;
line-height: 2em;
color: white;
background-color: black;
padding: 0.5em;
max-width: 360px;
}

How do I evenly distribute a group of spans across a div?

I have an aside on the side of my webpage that contains span blocks that contain tags for blog posts. Right now, they're set up with display: inline-table that put multiple on each line and then go to the next line as overflow.
If possible (and JavaScript is okay, but CSS is preferred), how can I get these spans to take up the entire width inside of the div so I don't have the "rough edge" to the right? I'd like to either increase the margins between the span blocks or I'd be okay with increasing the width of the span as well.
Here's the code I currently have:
body {
background-color: #333;
color: #333332;
}
aside {
background-color: white;
width: 300px;
height: 300px;
margin: auto;
}
h2 {
margin: 24px;
padding-top: 24px;
}
.tag-wrapper {
padding: 0px 24px;
}
span {
display: inline-table;
text-transform: uppercase;
background-color: #F77C2F;
margin: 4px 2px;
padding: 8px;
}
<div class="container">
<aside>
<h2>Tags</h2>
<div class="tag-wrapper">
<span>finance</span>
<span>if</span>
<span>pv</span>
<span>pivot tables</span>
<span>vba</span>
<span>test</span>
<span>test</span>
<span>test</span>
</div>
</aside>
</div>
A little flexbox magic will get the job done:
body {
background-color: #333;
color: #333332;
}
aside {
background-color: white;
width: 300px;
height: 300px;
margin: auto;
}
h2 {
margin: 24px;
padding-top: 24px;
}
.tag-wrapper {
padding: 0px 24px;
display: flex;
flex-flow: row wrap;
align-content: stretch;
}
span {
flex: 1 0 auto;
text-transform: uppercase;
background-color: #F77C2F;
margin: 4px 2px;
padding: 8px;
}
<div class="container">
<aside>
<h2>Tags</h2>
<div class="tag-wrapper">
<span>finance</span>
<span>if</span>
<span>pv</span>
<span>pivot tables</span>
<span>vba</span>
<span>test</span>
<span>test</span>
<span>test</span>
</div>
</aside>
</div>
The properties used are:
display: flex: this sets the display type of the container to flex (aka flexbox)
flex-flow: row wrap: makes items order in a row, and wrap as required.
align-content: stretch: makes items stretch to fill the flex direction (row).
flex 1 0 auto: makes the items "growable" (1), but not "shrinkable" (0), and use self base width (auto) before distributing leftover space.
Is this what you are talking about? If so, just change the display of the span to block instead of inline-block.
body {
background-color: #333;
color: #333332;
}
aside {
background-color: white;
width: 300px;
height: 300px;
margin: auto;
}
h2 {
margin: 24px;
padding-top: 24px;
}
.tag-wrapper {
padding: 0px 24px;
}
span {
display: block;
text-transform: uppercase;
background-color: #F77C2F;
margin: 4px 2px;
padding: 8px;
}
<div class="container">
<aside>
<h2>Tags</h2>
<div class="tag-wrapper">
<span>finance</span>
<span>if</span>
<span>pv</span>
<span>pivot tables</span>
<span>vba</span>
<span>test</span>
<span>test</span>
<span>test</span>
</div>
</aside>
</div>

Oneline horizontal list with middle item that fits its content width

I have a horizontal list of items, arranged with display:table-cell.
The middle item can vary in content length, and it should expand accordingly.
And obviously its siblings should shrink to make space to it.
Here is a sample of what I did until now:
http://codepen.io/Pictor13/pen/mJoyXw
But the middle item still overflows over the right sibling, when the content grows.
Is it possible to achieve what I want? Are display: table-cell and white-space: nowrap the right approach?
Note: the width, if specified, should always be generic and not fixed to a specific px/em.
Wellll....flexbox can do that.
.container {
background-color: yellow;
padding: 1px;
}
li {
text-align: center;
border: 2px solid #ccc;
background-color: green;
color: red;
list-style: none;
}
ul {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
padding: 0;
margin: 3px;
background-color: brown;
}
li {
-webkit-box-flex: 1;
-webkit-flex: 1 0 auto;
-ms-flex: 1 0 auto;
flex: 1 0 auto;
}
input {
width: 270px;
width: inherit;
}
form {
background-color: blue;
margin: 0;
padding: 0;
}
<div class="container">
<ul class="list">
<li>B</li>
<li>C</li>
<li class="middle">
<form>
<input type="number" value="123123418190238901390812903823" min="1" max="123012301232138192738798127398712983" />
<span>to page and with some long content</span>
<button>go</button>
</form>
</li>
<li>E</li>
<li>A</li>
</ul>
</div>
Codepen Demo

<!DOCTYPE html> breaks out the layout

I have the following simple html code for a simple template:
<!DOCTYPE html>
<html>
<head>
<title>My new website</title>
<meta name="description" content="Simple website styled using flex box layout">
<meta http-equiv="refresh" content="60">
<link rel="stylesheet" type="text/css" href="style1.css">
</head>
<body>
<div class="mainContainer">
<nav class="mainMenu">
<ol>
<li>
Home
</li>
<li>
About
</li>
<li>
Contact Us
</li>
</ol>
</nav>
<div class="mainArea">
<aside class="leftBar">
<h3>Navigation side bar</h3>
<p>Still need to think better what I will implement here.</p>
</aside>
<article class="mainContent">
<h1>Welcome!</h1>
<p>Nice to meet you...</p>
</article>
<aside class="rightBar">
<h3>News</h3>
<p>No news for now.</p>
</aside>
</div>
<footer class="mainFooter">
<p>Copyright ©
someone
</p>
</footer>
</div>
</body>
</html>
But the layout broke after I added <!DOCTYPE html> at the beginning of the html code. Now it looks like this:
But it should look like this:
Not only the margins broke, for example also the navigation bar is not exactly how it should be. I searched around for a solution, and there are some problems related, but I simply cannot understand why there this problem.
Here you have the CSS code:
html, body{
height: 100%;
width:auto;
font: 14px Arial;
color:white;
background: #444;
}
/* links */
a{
text-decoration: none;
color: #00aefb;
}
a:visited{
color:#008efb;
}
a:hover{
color: #999;
}
/* flex elements */
.mainContainer, .mainFooter, .mainArea, .mainMenu, .mainMenu ol{
display: flex;
display: -webkit-flex;
display: -moz-flex;
}
/* Main container */
.mainContainer{
font-family: Georgia;
flex-direction: column;
-webkit-flex-direction: column;
-moz-flex-direction: column;
}
/* mainMenu and footer */
.mainMenu, .mainFooter{
background: #555;
border: 1px solid white;
border-radius: 2px;
padding: 10px;
}
/* Just footer */
.mainFooter {
text-align: center;
font: 15px Arial;
min-height: 60px;
justify-content: center;
-webkit-justify-content: center;
-moz-justify-content: center;
align-items: center;
-webkit-align-items: center;
-moz-align-items: center;
}
/* Main area of contents */
.mainArea{
color: white;
border: 1px solid white;
border-radius: 2px;
margin: 20 0 20 0;
min-height:800px;
}
/* Main area of the main area */
.mainContent{
background: #eee;
color: black;
padding:20px;
flex: 2 2 50%;
-webkit-flex: 2 2 50%;
-moz-flex: 2 2 50%;
}
/* Left and right side bars */
.leftBar, .rightBar{
padding: 10px;
flex: 1 1 15%;
-webkit-flex: 1 1 15%;
-moz-flex: 1 1 15%;
}
/* mainMenu bar at the top */
.mainMenu {
font: 16px Arial;
justify-content: center;
-webkit-justify-content: center;
-moz-justify-content: center;
padding: 0;
}
.mainMenu ol {
list-style: none;
padding: 0; /* Removes annoying indentation */
margin: 0;
text-align: center;
}
.mainMenu ol li{
display: inline;
padding: 20px;
margin: 0 30 0 30;
}
li:hover, li.active{
background: #222;
color: #999;
border-radius: 5px;
}
#media all and(max-width: 640px){
.mainArea{
flex-direction: column;
-webkit-flex-direction: column;
-moz-flex-direction: column;
}
.mainMenu {
font: 18px Arial;
flex-direction: column;
-webkit-flex-direction: column;
-moz-flex-direction: column;
}
.mainMenu ol {
flex-direction: column;
-webkit-flex-direction: column;
-moz-flex-direction: column;
align-items:stretch;
-webkit-align-items:stretch;
-moz-align-items:stretch;
}
.mainMenu ol li {
margin: 0;
padding: 10px;
}
.mainContainer .mainArea {
border: 0;
border-radius: 0;
}
.mainContent{
order: -1;
-webkit-order: -1;
-moz-order: -1;
margin: 0 0 20 0;
border: 1px solid white;
border-radius: 2px;
}
.leftBar {
margin: 0 0 20 0;
border: 1px solid white;
border-radius: 2px;
}
.rightBar{
border: 1px solid white;
border-radius: 2px;
}
}
I wouldn't say that adding <!DOCTYPE html> breaks out the layout. The doctype tells the browser how to interpret the HTML and CSS, if you don't specify one, then the browser goes in quirk mode, and the display is different from a strict mode.
By adding the <!doctype html>, some of your CSS styles become incorrect and the browser does interpret them the best way that it can. For example, one of the issues that you have is that there are some non-zero numeric values without specifying the unit (e.g.: margin: 20 0 20 0;).
You are missing .mainMenu { margin-bottom: 10px; }
Or alternatively, if you want to use <!DOCTYPE html> then fix this .mainArea { margin: 20px 0 20px 0; }, you did not mention any units.
CSS Units
CSS has several different units for expressing a length.
Many CSS properties take "length" values, such as width, margin,
padding, font-size, border-width, etc.
Length is a number followed by a length unit, such as 10px, 2em, etc.
A whitespace cannot appear between the number and the unit. However,
if the value is 0, the unit can be omitted.
For some CSS properties, negative lengths are allowed.
There are two types of length units: relative and absolute.
Reference

Resources