i'm working on a layout and I can't figure out how to get these columns to be equal height, specifically the green areas when the text wraps. Can you help?
My html template, with more .category-containers inside...
<div class="flex-container">
<div class="category-container">
<a href="#" class="img-gallery-col medium-internal-page-static-image" style="background-image: url('http://placehold.it/800/800');">
</a>
<h4 class="text-center">Salads & Sides</h4>
</div>
</div>
My css for the flex-container is...
.flex-container {
width: 100%;
display: flex;
flex-wrap: wrap;
align-items: flex-start;
}
Here's a coden link if that helps http://codepen.io/johnsonjpj/pen/evopaV?editors=1100
EDIT: I have updated the pen and added a height to the category-container and also made it display: flex. Then I added flex-grow to the h4. How can I get it vertically center inside that green area?
You have no heights defined anywhere in your code. Therefore, there is no reason for your text blocks to have equal height. Their height is defined by the content, which is a default setting (height: auto).
You need to define a height somewhere in your layout, whether high up on the body element or on a container element closer to the text. You can then establish equal heights and use flex properties for vertical and horizontal alignment.
As you resize the page, there's points which all of the text boxes are on one line, and points where they're all on two lines (resize browser to wide/narrow).
Since you have this issue in a middle ground of sorts, I would recommend using CSS #media queries to change the height property of .category-container h4 to predetermined values which you know will look okay.
Related
I have the following simple layout (with the exception that the textarea becomes a Code Mirror at runtime):
<div class="columns">
<div class="column is-paddingless" style="background: indigo;">
<textarea id="code-editor"></textarea>
</div>
<div class="column">
</div>
</div>
The problem is - the first column does not fill the vertical space of the page (below the tabs) - rather it just wraps the height of the textarea. For instance:
Is there a way to make the column fill the page?
Flexbox should work for you! For your reference I love this guide: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
Setting up your .columns like this should do the trick:
.columns {
display: flex;
flex-direction: row; // this is default
align-items: stretch; // this will stretch the children vertically
}
Unsure how you have .column styled (ie height: 100%) but let me know if this does NOT work and I can troubleshoot further.
Give a class or id or just write inline style and do
min-height : XXvh;
Where xx is how VH you need.
According to MOzila devaloper
vh
Equal to 1% of the height of the viewport's initial containing block.
So... I got this code: https://jsfiddle.net/jmg63s3e/1/
The code actually works fine if you resize the browser window until you have the text inline with the image and that's what I'm trying to achieve, but if you resize it down eventually the text drops below the image even if the wrapper width is a lot smaller than the window width.
My only purpose is to have:
the whole wrapper centered both vertically and horizontally in the browser window. Its total width and height unknown, depending on its children
row1 and row2 must not be inline: row2 must be below row1
All the elements inside row1 (the image and the text containing 2 spans) must be inline with each other
And well, the spinner inside row2 must also be centered inside the row but that was never a problem whatever solution I tried
As a matter of fact the only dynamic element in the whole code is the first span which in the example contains Player #1, since it should be the name of the player and it can be anything, any length.
Of course if I wanna make it responsive I will have to use media queries or dynamically change widths and heights and font-sizes with JS, and I'm willing to do so. My problem here is only the wrapper itself and the text that drops below the image even if the wrapper width is a lot smaller than the window width, so I'm asking for a solution that works as long as the wrapper width is smaller than the window width. When the wrapper width drops below the window width, I will handle the style with responsive media queries or JS. I would just like to have the wrapper to be centered both vertically and horizontally in the window, and its size to be dynamic and depending on children.
I've already tried any solution I could think of, but with an unknown wrapper width I just can't figure it out. Can someone help me please? I'm open to any suggestion and any solution, as long as it's pure CSS and it doesn't involve JS. Thanks everyone in advance
You can use flexbox to fix these problems.
Here's an updated fiddle with old CSS commented out: https://jsfiddle.net/jmg63s3e/3/
First, to align the wrapper both horizontally and vertically you need to make the parent container a flex container with display: flex and use justify-content: center and align-items: center. You also need to set a height or else it will wrap to the height of the child and not give you the centering effect. I used the following. The height can be whatever you need it to be.
.trump-waiting {
display: flex;
justify-content: center;
align-items: center;
font-size: 0;
overflow: hidden;
height: 100vh;
}
Next, I used display: flex on the wrapper and flex-direction: column to make sure they are all lined up like we want them to be.
.trump-waiting .wrapper {
display:flex;
flex-direction:column;
To fix row1, again I used flexbox and removed the inline-block and the set height. You could set the height as long as you take care of resizing the font in the text divs, with media queries for instance. Otherwise, with an explicit height, the font at the size it's at now will break out of their containers. Without explicitly setting the height, the containers will adjust in size.
.trump-waiting .row1 {
display: flex;
flex-direction: row;
/* display: inline-block; */
/* height: 60px; */
background-color: yellow;
}
I also added flex-shrink:0 to .image to keep it from shrinking on resize.
To keep Player #1 and 'is choosing the trump suit' inline, I also added display: flex and flex-direction: row to .row keep them on the same line.
Finally, to align the loader, I did the vertical/horizontal alignment trick used above, plus added some padding to the div to give it some space and removed the old css.
.trump-waiting .row2 {
display: flex;
justify-content: center;
align-items: center;
padding: 16px 0 16px 0;
/* display: block; */
/* margin-top: 50px; */
The last step would be to use media queries to adjust the font-sizes on .text spans so the font doesn't expand their container on resize.
Many ways to skin a cat and I'm sure others will have different perhaps better solutions, but hope this helps. There's a great summary of flexbox here if you need it. I may have left out a change in this summary, but it should all be in the fiddle.
EDIT: Realized I made a mistake summarizing the css in the jsfiddle and also removed a redundant css property. Now updated.
This question already has answers here:
Make container shrink-to-fit child elements as they wrap
(4 answers)
Closed 5 years ago.
I am trying to center two div elements side by side in a row with flexbox (display:flex).
The first div element, on the left, just has an image.
The second div element, on the right, has left-aligned inline text of unspecified length.
When the line of text is short enough to fit on one line, both divs are aligned and justified to the center as I expect.
When the line of text is long enough to wrap onto two lines, the second div element does not wrap itself around the content as I expect. Instead, it leaves a large white space on the right side of the div.
I mocked up an example here: http://codepen.io/anon/pen/NGqYQX?editors=110. Vary your browser window's width to see what I mean.
How can I set the second div element to shrink itself to fit the text, so that both div elements appear centered?
.flexbox-container {
display: flex;
justify-content: center;
align-items: center;
}
.div1 {
margin-right: 30px;
}
.div2 {
font-size: 48px;
line-height: 48px;
text-align: left;
}
<div class="flexbox-container">
<div class="div1">
<img src="http://dreamatico.com/data_images/kitten/kitten-2.jpg" width="150px">
</div>
<div class="div2">
This is an example of a line of text.
</div>
</div>
<br>
<div class="flexbox-container">
<div class="div1">
<img src="http://dreamatico.com/data_images/kitten/kitten-2.jpg" width="150px">
</div>
<div class="div2">
This is an example of a much loooooooooooooonger line of text.
</div>
</div>
Here is a Photoshop mockup showing what I am trying to do:
In order to achieve your goal (as specified in your second image) we need to make a few adjustments to your HTML and CSS. Everything can be done with flexbox.
HTML
<div id="flex-container-main">
<div class="flex-container-child">
<figure>
<img src="http://dreamatico.com/data_images/kitten/kitten-2.jpg" width="150px">
</figure>
<p>This is an example of a line of text.</p>
</div>
<div class="flex-container-child">
<figure>
<img src="http://dreamatico.com/data_images/kitten/kitten-2.jpg" width="150px">
</figure>
<p>This is an example of a much loooooooooooooonger line of text.</p>
</div>
</div><!-- end #flex-container-main -->
CSS
#flex-container-main {
display: flex;
flex-direction: column;
align-items: center;
}
.flex-container-child {
display: flex;
align-items: center;
min-height: 127px;
width: 75%;
margin: 10px;
}
figure {
margin: 0 20px 0 0;
}
img {
width: 150px;
height: 127px;
vertical-align: bottom;
}
p {
font-size: 48px;
margin: 0;
}
Revised Codepen Demo
Here's what's happening...
Your question asks:
Keeping flexbox centered when text wraps to 2 or more lines
I am trying to center two div elements side by side in a row with flexbox (display:flex).
Let's quickly go over your two images.
Image 1
Image 2
In image 1 all flex items are actually centered. The blue highlight from Chrome Dev Tools emphasizes this point. Each item is perfectly centered on the screen.
Yes, it does get a bit clunky as you re-size the screen smaller – mostly because of the large font size – but the flex items remain centered nonetheless.
In image 2, the flex items are not evenly centered. What you've created in your mock-up is more like a column containing both flexboxes, and the column is centered. But individually only the first row is centered on the screen.
A couple of notes about your code:
With justify-content declared on the flex containers, you are centering the flex items. The flex container itself is not centered.
Since both flexboxes are direct children of the <body>, and <body> has no defined width, the flexboxes align themselves in relation to the viewport.
So to achieve the effect you want we can wrap all your existing mark-up in a new flex container (#flex-container-main). This converts the original flex containers into flex items, which can then be evenly centered as a group.
The new flex items (now classed as .flex-container-child) are given a width to create space and a minimum height based on the height of the image. Each flex item is also declared a flex parent (display: flex) which allows us to use flex properties on child elements. In particular, this is useful for vertically centering the text (as shown in your images).
(Note that my use of HTML semantic elements is not necessary for the code to work. If you prefer the original div tags just swap them back. The important adjustment is the new parent container.)
Lastly (and this may not be important to your layout but just in case), browsers normally give images a small gap of whitespace under their bottom border. This is used to accommodate descenders. With vertical-align: bottom, this space is removed. (For more details see my answer about descenders.)
So I basically have 2 containers which are the same width, but can have varying "heights" depending on their content. I wanted both to also have the same height regardless, adopting the height of whichever was tallest, so I used a flexbox which worked perfectly.
Now the thing is I'm wondering if it's possible to align content at the bottom of both of them.
I essentially have:
<div class="flex-box">
<div class="row event">MetTalks...</div>
<div class="row shop">Digital Shop...</div>
</div>
.flex-box {
display: flex;
width: 66%;
flex-direction: row;
justify-content: flex-start;
padding: 30px;
}
.row {
flex: 1;
}
As you can see here, they equally take up the row (I only wanted them to span the first 2/3) like I wanted to, and their heights are the same. But I want to be able to align the buttons at the bottom.
I've tried a bunch of things that aren't working, such as making a table div inside, but I can't get the height to stretch to 100% of the row divs
I also can't use position:absolute for the buttons because then they overlap the text as they're taken out of the height calculations.
I even tried making a vertically aligned flex container inside each one, but that also doesn't stretch to 100% height
You can achieve what you want with absolute positioning, without overlapping the text. You can set a fixed height to the buttons, let's say 50px. Then, you have to apply padding-bottom to the box equal to button's height, + top & bottom margin. So, if you want the button positioned 20px from bottom of the box, you can add a 90px (50 + 20 + 20) padding-bottom to the box. If you can submit the code to jsfiddle, it would be much easier to help.
When using css flexbox the three main browsers appear to behave entirely differently in certain areas.
In this case I am trying to create a grid of images:
<div class="container">
<div class="photo"></div>
<div class="photo"></div>
<div class="photo"></div>
<div class="photo"></div>
<div class="photo"></div>
<div class="photo"></div>
</div>
.container {
display:inline-flex;
flex-flow : column wrap;
align-content : flex-start;
height : 100%;
}
In this example I need a container, itself containing several div elements set up to flow from top to bottom and wrapping when they reach the bottom. Ultimately providing me with columns of photos.
However I need the container to expand horizontally to accommodate the wrapped elements:
Here is a quick jsFiddle to demonstrate.
The behaviour is as follows:
IE 11 - Correct, the container stretches horizontally to wrap each column of wrapped elements
Firefox - The container only wraps the first column of elements, with the rest overflow out.
Chrome - The container always stretches to fill the width of its parent, whatever that may be.
In this instance I would like to achieve the behaviour of IE11 in the other two browsers. Therefore my question is, how can I make a flexbox container expand horizontally to match its column wrap contents.
Thanks in advance.
It's curious that most browsers haven't implemented column flex containers correctly, but the support for writing modes is reasonably good.
Therefore, you can use a row flex container with a vertical writing mode. This will swap the block direction with the inline direction, and thus the flex items will flow vertically. Then you only need to restore the horizontal writing mode inside the flex items.
.container {
display: inline-flex;
writing-mode: vertical-lr;
flex-wrap: wrap;
align-content: flex-start;
height: 350px;
background: blue;
}
.photo {
writing-mode: horizontal-tb;
width: 150px;
height: 100px;
background: red;
margin: 2px;
}
<div class="container">
<div class="photo">1</div>
<div class="photo">2</div>
<div class="photo">3</div>
<div class="photo">4</div>
<div class="photo">5</div>
<div class="photo">6</div>
<div class="photo">7</div>
<div class="photo">8</div>
<div class="photo">9</div>
</div>
This approach may have its own bugs in edge cases, especially if you mix advanced layout techniques like floats and nested flexboxs. But for most cases it seems to work properly.
The spec says that what you're doing should work, but it's implemented incorrectly in every major browser besides Internet Explorer / Edge, making multi-line inline-flex column layouts useless at present for most developers. Here's a Chromium bug report providing an example that is effectively identical to yours, and noting that it renders incorrectly in Chrome, Safari, and Firefox.
The argument from spec is more complicated than I'm able to understand, but the key point is that Flexible Box Layout Module Level 1 spec defines the intrinsic cross-size of a flex container (that is, the intrinsic height of a flex-direction: row flex container or the intrinsic width of a flex-direction: column flex container) in the section Flex Container Intrinsic Cross Size. There, it is stated:
For a multi-line flex container, the min-content/max-content cross size is the sum of the flex line cross sizes
That is, the intrinsic width of a flex-direction: column flex container should be the sum of the widths of its columns, as you'd expect. (There is more complexity than this, and I don't understand it all, but I believe the above to be broadly true.) However, Chrome, Firefox, and Safari all calculate this width incorrectly; setting width: min-content or width: max-content on a column wrap flex box in Chrome, you can clearly see that the width is set to the width of the widest single element.
A silly Chrome-specific workaround exists, but is probably best avoided. Until the bug is fixed, this part of the Flexbox model simply doesn't work as designed and there's no clean solution available.
It seems this issue cannot be solved only with CSS, so I propose you a JQuery solution
container width = position of the last child - position of the container + width of the last child (including margin)
Code :
$(document).ready(function() {
$('.container').each(function( index ) {
var lastChild = $(this).children().last();
var newWidth = lastChild.position().left - $(this).position().left + lastChild.outerWidth(true);
$(this).width(newWidth);
})
});
Demo :
http://jsfiddle.net/qzea320L/
You have a column layout distribution with a fixed height container.
When you set the flex-direction to column you define the Vertical axis as the main axis.
In flexbox that means it will fill up the available height and then create a new column.
In this JSBIN I use javascript to change the container's height and, because of that, you will see the child items move.
PS: you shouldn't rely on IE behavior since their flex support is recent.
Another possible approach:
.container {
column-count: 2; /*or whatever */
}
.container > div {
display: inline-block;
}
https://developer.mozilla.org/en-US/docs/Web/CSS/column-count
You may also need to adjust margin-top of .container > div:first-child if they don't align to the top.