I have 4 boxes that I would like to resize as the size of my window changes. Box 1 will shrink, however box 2, 3 and 4 do not. What am I doing wrong?
.contents {
display: flex;
justify-content: flex-end;
min-width: 0px;
}
.contents div:first-child {
flex-grow: 1;
padding: 5px;
}
.contents div {
border-left: 1px solid red;
flex-shrink: 1;
min-width: 0px;
overflow: hidden;
padding: 5px 100px;
}
<div class="contents">
<div>1 Really long text goes in here, really long text goes in here.</div>
<div>2 Lorem</div>
<div>3 Ipsum</div>
<div>4 Dolor</div>
</div>
http://codepen.io/anon/pen/OppdmQ?editors=1100#0
Thank you.
You have 100px padding on the left and right of each item (padding: 5px 100px). That's 200px of inflexible width right off the bat. Try this method instead:
.contents div {
border-left: 1px solid red;
flex: 0 1 200px; /* can't grow, can shrink, start at 200px width */
min-width: 0px;
overflow: hidden;
padding: 5px;
text-align: center;
}
revised codepen
You won't achieve the desired effect if you are going to use padding since it will take up that much of space no matter what your screen size is. So, in that case you need to change the padding using media break points or change the flex properties according to the size of the screen.
Related
I need to put 3 columns inside a container. They are supposed to have the same width and evenly distributed. I use flex for that and it works fine.
In the end I need to insert a collection of "cards" in each column ... Because the number of cards can cause the columns to have a greater height than what can be displayed in the browser, the container (the parent of the columns) has overflow set to scroll. So when that happens you can still scroll down to look at the cards that are at the bottom of the column.
I have two problems that I'd like to fix:
1) As soon as I insert a card in the left column, that columns becomes larger than the other two. If I set the column to flex and set flex-grow to 0 on the card, it makes no difference. I am not sure why?
EDIT:
I fixed #1 by setting width: 33%; on .column.
===========================================================================
2) The left column is not drawn passed the bottom boundary of the browser, even though it contains cards causing the container to potentially overflow. What I want to do is be sure that the column "contains" the cards. How could I achieve that (using flex or not)?
I created a fidle and illustrated this problem with the figure below.
JSFIDDLE is here
1) As soon as I insert a card in the left column, that columns becomes
larger than the other two. If I set the column to flex and set
flex-grow to 0 on the card, it makes no difference. I am not sure why?
flex-grow does not define the width, it define how the available space should be distributed.
You could use flex-basis: 33.333%
2) The left column is not drawn passed the bottom boundary of the
browser, even though it contains cards causing the container to
potentially overflow. What I want to do is be sure that the column
"contains" the cards. How could I achieve that (using flex or not)?
Change the height: 100% on container to min-height: 100%
Stack snippet
html, body
{
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
.container
{
display: flex;
flex-direction: row;
border: 2px solid black;
overflow: scroll;
padding: 0;
margin: 0;
min-height: 100%; /* changed to 'min-height' */
width: 100%;
box-sizing: border-box;
}
.column
{
display: flex;
flex-direction: column;
flex: 1 1 auto;
background: grey;
margin: 5px;
}
.article
{
margin: 5px;
background: white;
height: 100px;
border: 1px solid orange;
}
<div class="container">
<div class="column">
<div class="article">article1</div>
<div class="article">article2</div>
<div class="article">article3</div>
<div class="article">article4</div>
<div class="article">article5</div>
<div class="article">article6</div>
<div class="article">article7</div>
</div>
<div class="column">col 2</div>
<div class="column">col 3</div>
</div>
To make the columns equal width, instead of flex: 1 1 auto, use flex: 1 1 0 (which is the same as flex: 1).
With flex-basis: auto the width of each column is based on its content, so equal width columns aren't guaranteed.
With flex-basis: 0, the width of all columns is an equal distribution of space in the container.
Here's a more complete explanation of flex-basis and the difference between auto and 0.
Make flex-grow expand items based on their original size
To make the divs respect their height: 100px, add flex-shrink: 0. Flex items have flex-shrink: 1, by default.
Here's a more complete explanation:
What are the differences between flex-basis and width?
To get the container to follow along, see the other answer to this question.
html,
body {
margin: 0;
padding: 0;
}
.container {
display: flex;
flex-direction: row;
border: 2px solid black;
overflow: scroll;
padding: 0;
margin: 0;
min-height: 100vh;
box-sizing: border-box;
}
.column {
display: flex;
flex-direction: column;
background: grey;
margin: 5px;
flex: 1; /* adjustment */
}
.article {
margin: 5px;
background: white;
border: 1px solid orange;
flex: 0 0 100px; /* adjustment */
}
<div class="container">
<div class="column">
<div class="article">article1</div>
<div class="article">article2</div>
<div class="article">article3</div>
<div class="article">article4</div>
<div class="article">article5</div>
<div class="article">article6</div>
<div class="article">article7</div>
</div>
<div class="column">col 2</div>
<div class="column">col 3</div>
</div>
I have a problem with Firefox on a really specific graphic implementation.
I think you may understand the problem just by testing this fiddle: on firefox you'll see the problem, on any other browser you'll see the expected result (including IE9).
Design I need:
PNG illustration
I have a main block (dashed border) with a fixed width.
There is 2 lines, one above the other, within the main block. The 2 lines must be align on the right of the main block
Each line contains 2 children. The left ones have a dynamic text (gray background), the right ones are optionnals (blue background). The above right one contains an icon (orange) with a fixed width, the bellow right one is a dynamic temperature (with one decimal maximum).
Blocks are separated by a fixed 5px margin.
Texts and icon must be vertically centered.
In any case, the 2 lines need to have the same width: the smaller one takes the width of the bigger one.
If one line (or both) becomes too large for the main block, the left text (gray background) automatically linebreak.
HTML Code:
<div class="main-wrapper">
<div class="container">
<div class="content upper">
<div class="right-block"><!-- This block is optionnal -->
<div class="icon"></div>
</div>
<div class="left-block">
<div class="vertically-centered">
<p>
Some dynamic text
</p>
</div>
</div>
</div>
<div class="content lower">
<div class="right-block"><!-- This block is optionnal -->
<div class="vertically-centered">
<span>
21,5°
</span>
</div>
</div>
<div class="left-block">
<div class="vertically-centered">
<p>
Some other dynamic text
</p>
</div>
</div>
</div>
</div>
</div>
CSS Code:
/* utilities */
.vertically-centered {
display: table;
height: 100%;
width: 100%;
}
.vertically-centered > * {
display: table-cell;
vertical-align: middle;
}
/* custom styles */
.container {
display: inline-block;
float: right;
max-width: 100%;
}
.content {
width: 100%;
margin: 5px 0px;
height: 85px;
}
.right-block, .left-block {
height: 100%;
}
.right-block {
float: right;
font-size: 42px;
margin-left: 5px;
background-color: lightblue;
}
.left-block {
font-size: 25px;
line-height: 25px;
overflow: hidden;
padding: 0 20px;
text-align: left;
background-color: lightgray;
}
.upper .right-block {
width: 85px;
}
.lower .right-block {
padding: 0 15px;
}
.icon {
position: relative;
top: 20%;
left: 20%;
width: 60%;
height: 60%;
background-color: orange;
}
What I already tried:
Put a display: inline-block on the .left-block div, as suggested here, but it doesn't satisfy the need to have the same width on both lines.
Put a display: inline-block on the .content div; makes the line 100% width on other browsers, and create a big right gap within the .left-block on firefox.
Use white-space: nowrap on the .left-block; didn't help.
Make the .left-block div floating (right or left), but it doesn't work if the text is too large for the main container
And a lot of other things but not a single one compatible with all the browsers (Chrome, Firefox, Safari, IE9+, Edge)...
A precision although I don't think it will change anything: it is responsive.
I'm trying something with flexbox but... IE9... If anybody has a suggestion.
You can use the CSS word-break property to allow line breaks in the middle of long words:
.content {
width: 100%;
margin: 5px 0px;
height: 85px;
word-break: break-all;
}
I found out a solution with flexbox!
I added a display: flex to the .content div with flex-direction: row-reserve to keep the order of the element and still be able to use float: right for IE9.
In addition, there is a flex: auto property on .left-block divs to take as much space as possible (Note: IE11 needs flex-basis to be set to be able to calculate the space wanted by the flex-grow property. That's why I used auto instead of 0 on the flex property. See details)
The completed CSS code
.content {
width: 100%;
margin: 5px 0px;
height: 85px;
display: flex; /* Initialize flexbox */
flex-direction: row-reverse; /* keep the order of the element */
border: 1px dashed gray;
}
.left-block {
font-size: 25px;
line-height: 25px;
overflow: hidden;
padding: 0 20px;
text-align: left;
background-color: lightgray;
flex: auto; /* the text blocks take all the available space */
}
Here's the fiddle with the correction. Sometimes IE9 takes 2 lines of text instead of 1 (the text is 2px larger that the container, I don't know why...) but atleast it's readable!
Okay, so i have my parent DIV (black), and 3 children.
CSS rules:
#parent{
height:130px;
}
#description{
max-height: 80px;
}
And that's actually pretty much it for now.
What I am trying to do
#title should resize according to text inside. It can be from one, to 5-6 lines of text (it's a span, can be div - any difference?)
#city is like 99% of the time one line text (one word actually). Might happen text gets too long, and needs to be wrapped to two lines.
#description is a div, which CANNOT go outside the parent box. I need it to have dynamic height - as for later, i use some plugin to cut the text according to height of it and add "..." in the end.
Image shows what it looks like now, when i put too much text in title, and i would like, description to be max 80px, but CAN be less, if #title takes more place.
JsFiddle
EDIT: Changed image
You may want to try flexbox for such a layout. It may not provide you with a pixel perfect layout on the kind of complex rules you have, but it will still be a powerful way to control.
Fiddle: https://jsfiddle.net/abhitalks/kwq2L3y7/6/
Snippet:
#parent {
border: 1px solid black;
height: 200px; width: 80px;
float: left; margin: 16px;
display: flex; flex-direction: column;
}
#title {
flex: 2 1 auto; /* can grow twice, can shrink, auto height */
border: 1px solid red;
overflow: auto;
}
#city {
flex: 1 1 20px; /* can grow, can shrink, accommodate in 20px */
border: 1px solid green;
overflow: hidden;
}
#description {
flex: 0 1 80px; /* cannot grow, can shrink, accommodate in 80px */
border: 1px solid blue;
overflow: hidden;
}
<div id="parent">
<div id='title'>Title</div>
<div id="city">City</div>
<div id="description">Description</div>
</div>
<div id="parent">
<div id='title'>Long Title can be of several lines and can grow many lines</div>
<div id="city">City can be in 2 lines</div>
<div id="description">Description which is very long and it will not grow beyond 80px</div>
</div>
<div id="parent">
<div id='title'>Title</div>
<div id="city">City can be in 2 lines what if it is larger</div>
<div id="description">Description will remain at 80px</div>
</div>
What you want to get, you need to set height: 100% in #description.
Use like this:
#parent{
border: 2px solid black;
overflow: hidden;
}
#description{
border: 2px solid blue;
height: 100%;
}
demo
You may display the text in ellipsis.
I don't get what you exactly want to do, but you should have a look on the 'overflow' method with for example:
#parent{
overflow-y: hidden;
}
or
#parent{
overflow-y: scroll;
}
If you want the height to be dynamic, you could try use min-height
#parent {
min-height:130px;
width: 80px;
}
#description {
min-height: 80px;
}
https://jsfiddle.net/arty_/x8f7v25h/
Here is an example I'm working with:
http://jsfiddle.net/adyjzbuh/18/
Here is the code:
<div class="box1">
<div class="box2">Some text</div>
</div>
<div class="box1">
<div class="box2">Some more text, actually, 2 lines of textalicious text</div>
</div>
<div class="box1">
<div class="box3">Some more text, actually, 2 lines of textalicious text</div>
</div>
<div class="box1">
<div class="box4">Some more text, actually, 2 lines of textalicious text</div>
</div>
Here is the CSS:
.box1 {
width: 300px;
border: 1px solid black;
padding: 10px;
text-align: center;
}
.box2 {
display: table;
margin: 0px auto;
border: 1px solid black;
padding: 10px;
text-align: left;
}
.box3 {
display: inline-block;
margin: 0px auto;
border: 1px solid black;
padding: 10px;
text-align: left;
}
.box4 {
display: table-cell;
margin: 0px auto;
border: 1px solid black;
padding: 10px;
text-align: left;
}
As you can see, the first block does exactly what I want. The margins automatically adjust, the block is centered as intended. The issues come when there is multiple lines of text. When I use the same style for the next block with multiple lines of text, the block adjusts the width to 100% of the available space, leaving a big gap on the first line and block not appearing centered.
I tried changing the display to inline-block and table-cell but it does not work (as evidenced by the third and fourth block). I've searched everywhere for solutions and none have worked.
The outer container will always be 300px and the inner block will always have to be flexible and adjust to multi-line text. Any solutions/examples would be greatly appreciated, thank you.
EDIT I forgot to mention the client specifically wants the text to align to the left.
I would add:
text-align: center
or
text-align:justify
instead of:
text-align:left
Is that what you expected to look like?
You might want to put a max-width: 50%; on your innerboxes. The reason is your solution doesn't really work the way you want is your margins are set to auto, so the margin is calculated of the width. So if say your width would be 50% of the parent container (in this case .box1), the margins are automatically calculated to fill up the other 50%, 25% for each side.
Max-width could fix your problem, the innerboxes are still flexible, but only will take up 50% of the width.
.box1 {
width: 300px;
border: 1px solid black;
padding: 10px;
text-align: center;
}
.box2 {
display: table;
margin: 0px auto;
border: 1px solid black;
padding: 10px;
text-align: left;
max-width: 50%;
}
Not sure what you are looking for ultimately, but here is a working example, with using table method, like you have, but using
display:table;
display:table-cell;
accordingly with text aligned in the middle, and centered or left aligned.
I'm trying to set up a flexbox layout with three columns where the left and right columns have a fixed width, and the center column flexes to fill the available space.
Despite setting up dimensions for the columns, they still seem to shrink as the window shrinks.
Anyone know how to accomplish this?
An additional thing I will need to do is hide the right column based on user interaction, in which case the left column would still keep its fixed width, but the center column would fill the rest of the space.
#container {
display: flex;
justify-content: space-around;
align-items: stretch;
max-width: 1200px;
}
.column.left {
width: 230px;
}
.column.right {
width: 230px;
border-left: 1px solid #eee;
}
.column.center {
border-left: 1px solid #eee;
}
<div id="container">
<div class="column left">
<p>Anxiety was a blog series that ran in the New York Times Opinion section from January 2012 to July 2013. It featured essays, fiction, and art by a wide range of contributors that explored anxiety from scientific, literary, and artistic perspectives.</p>
</div>
<div class="column center">
<img src="http://i.imgur.com/60PVLis.png" width="100" height="100" alt="">
</div>
<div class="column right">
Balint Zsako
<br/> Someone’s Knocking at My Door
<br/> 01.12.13
</div>
</div>
Here's a JSFiddle: http://jsfiddle.net/zDd2g/185/
Instead of using width (which is a suggestion when using flexbox), you could use flex: 0 0 230px; which means:
0 = don't grow (shorthand for flex-grow)
0 = don't shrink (shorthand for flex-shrink)
230px = start at 230px (shorthand for flex-basis)
which means: always be 230px.
See fiddle, thanks #TylerH
Oh, and you don't need the justify-content and align-items here.
img {
max-width: 100%;
}
#container {
display: flex;
x-justify-content: space-around;
x-align-items: stretch;
max-width: 1200px;
}
.column.left {
width: 230px;
flex: 0 0 230px;
}
.column.right {
width: 230px;
flex: 0 0 230px;
border-left: 1px solid #eee;
}
.column.center {
border-left: 1px solid #eee;
}
Despite setting up dimensions for the columns, they still seem to shrink as the window shrinks.
An initial setting of a flex container is flex-shrink: 1. That's why your columns are shrinking.
It doesn't matter what width you specify (it could be width: 10000px), with flex-shrink the specified width can be ignored and flex items are prevented from overflowing the container.
I'm trying to set up a flexbox with 3 columns where the left and right columns have a fixed width...
You will need to disable shrinking. Here are some options:
.left, .right {
width: 230px;
flex-shrink: 0;
}
OR
.left, .right {
flex-basis: 230px;
flex-shrink: 0;
}
OR, as recommended by the spec:
.left, .right {
flex: 0 0 230px; /* don't grow, don't shrink, stay fixed at 230px */
}
7.2. Components of
Flexibility
Authors are encouraged to control flexibility using the flex shorthand
rather than with its longhand properties directly, as the shorthand
correctly resets any unspecified components to accommodate common
uses.
More details here: What are the differences between flex-basis and width?
An additional thing I need to do is hide the right column based on user interaction, in which case the left column would still keep its fixed width, but the center column would fill the rest of the space.
Try this:
.center { flex: 1; }
This will allow the center column to consume available space, including the space of its siblings when they are removed.
Revised Fiddle
Compatibility with older browsers can be a drag, so be adviced.
If that is not a problem then go ahead.
Run the snippet. Go to full page view and resize. Center will resize itself with no changes to the left or right divs.
Change left and right values to meet your requirement.
Thank you.
Hope this helps.
#container {
display: flex;
}
.column.left {
width: 100px;
flex: 0 0 100px;
}
.column.right {
width: 100px;
flex: 0 0 100px;
}
.column.center {
flex: 1;
text-align: center;
}
.column.left,
.column.right {
background: orange;
text-align: center;
}
<div id="container">
<div class="column left">this is left</div>
<div class="column center">this is center</div>
<div class="column right">this is right</div>
</div>
.column.left {
width: 230px;
flex: 0 0 230px;
}
.column.right {
width: 230px;
flex: 0 0 230px;
border-left: 1px solid #eee;
}
.column.center {
border-left: 1px solid #eee;
}