How do I align content at the bottom of a flex container w/o absolute? - html

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.

Related

Pure CSS: centering vertically and horizontally an absolute positioned element with width depending on children

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.

Equal Height Columns - Flexbox & flex-wrap: wrap

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.

How can I do this with CSS and HTML?

It's hard to explain, but I'll try. I am trying to create a grid of divs that will never go off the page horizontally. Hence, the bottom scroll bar will never show. Instead, divs that are pushed off the window will wrap to the next row. There may not be as many divs on the bottom row as there are on the previous. In this case, the divs on the bottom row must be centered in the window. As the window resizes, the margins between the divs should expand or shrink to equalize the space between them. If the window resizes enough, the number of columns should change to fit the divs. Hopefully this image will help:
float:left and display:inline-block are close, but they don't resize margins and are not centered. I would like this to be done with pure CSS and HTML, but I do know JavaScript if it is necessary.
You can achieve this by using flexbox
Demo
The key parts are:
.grid {
display: flex;
flex-wrap: wrap;
justify-content: space-around
}
.grid > div {
flex-basis: 300px;
}

margin auto not determined by width

In my rails app I have a container that holds from 1 to 4 divs that contain product images/text. There is 1 div if someone only selected 1 product in the previous page, 2 divs if someone selected 2 products, 3 div's if someone selected 3 products and so one. So the amount of product div's will varies and change depending on circumstance.
What I want:
the container and its div's to be centered.
if there is one div, I want that to be centered/margin:auto,
if there are two div's I want them to float/inline-block and margin centered,
I want all div's to be float and be centered but until all the div's fill the width of the container.
I tried to margin:auto the container, but I need a set width. If I have a set width then it wont grow depending on how many div's are in the container.
image1 http://www.image-maps.com/uploaded_files/3201312101150184_div1.png
image2 http://www.image-maps.com/uploaded_files/3201312101150184_div2.png
image3 http://www.image-maps.com/uploaded_files/3201312101150184_div3.png
width of div's inside container do not change.
My question has nothing to do with the width of the browser.
You can use text-align on the container if your insider div are inline-block:
.container {
text-align:center;
}
.container div.inside {
display:inline-block;
}
You can set display to inline-block for the divs and text-align to center for the container.
Just remember that text-align is inherited, so you'll need to re-set it to the desired value on the divs.
The only way I know of doing this is to use
display: inline-block;
on the divs, and it's container. Do not use
float: left;
and set
text-align: center;
on the container and it's parent.
margin: auto; can only center a div if it has an explicit width. A div that auto-grows does not have an explicit width and so margin: auto; won't work.
White space
Be careful when using inline-block as the browser will see whitespace in your markup and render it to the page, which can cause unwanted effects. Just make sure to trim out all the white-space between your divs.

Making a button element fill available width

There are a lot of "fill available space" questions on this site, but my issue is a bit particular in that I've already gotten a solution, but it doesn't work for buttons. I'd like to understand why this doesn't work for buttons, and how I can make it work. I imagine it's just some browser-style for the button element that I need to override.
I have two floating elements within a (fixed-width, if that matters) wrapping div. The right element has fixed width, and the left element should take up whatever width remains.
I can accomplish that by setting the right element to have fixed width and float: right, and leaving the left element without any special styling. This works perfectly for divs. It also works for spans, but only if I set display: block on them. For buttons, I can't get it to work at all. I tried block, inline-block, and every obscure width value I could find on the MDN.
http://jsfiddle.net/wjFbD/2/
I don't know why I didn't think of just wrapping the buttons in divs earlier. Here's what I've come up with:
http://jsfiddle.net/SkczB/2/
This involves the overflow: hidden box formatting context trick (which I suspected was going to make an appearance here, but couldn't quite see where to fit it in). Highlights:
The two buttons are wrapped in divs with class buttonWrapper.
Those divs are formatted according to the trick I outlined in the third paragraph, above. The right div has float: right and a fixed width, the left div has no special styling.
We now apply the box formatting context trick. The left div is given overflow: hidden, which causes it to make space for the right-floated div.
We can now apply a left margin to the right div, and change its width, and the left div will always be the right size.
The divs create the desired "fill available width" effect for us, now we just have to put the buttons inside the divs and give them a height and width of 100%.
If it's the left button you wanted to have a fixed width, then basically repeat the above steps with left and right swapped.
This may not be exactly what you're looking for here, but here's an option that seems to have worked out for me with your fiddle.
If you've got a fixed width div that the elements are contained in, you could split get the remaining width of the div after button A has been set to fill up, say, 100 pixels and then set button 2 to be the remaining size.
Alternatively, another option would be to run it as percentages 20%/80%, 30%/70%, that kind of thing. Here's a fiddle that achieves what you're looking for on just the button wrapper at the bottom. I've applied specific classes for it and added divs around each button for a bit more control. The button wrapper divs are set to 20% and 80% respectively, while the button is set to fill 100% of the containing space.
Here's the modified fiddle and the modfied HTML/CSS. Hope it helps for what you're looking for...
http://jsfiddle.net/wjFbD/7/
HTML
<div class="btnWrapper">
<div class="buttonWrapperB">
<button class="left">
button Left
</button>
</div>
<div class="buttonWrapperA">
<button class="right">
button Right
</button>
</div>
</div>​
CSS
.btnWrapper
{
width: 100%;
background-color: #FEE;
border: 2px solid black;
margin-bottom: 10px;
height: 50px;
}
.buttonWrapperB{
float: left;
width: 20%;
}
.buttonWrapperB button{
width: 100%;
height: 50px;
}
.buttonWrapperA{
float:left;
width: 80%;
}
.buttonWrapperA button{
width: 100%;
height: 50px;
}
​
I adjusted the background opacity of your .right elements to see what was going on below them. It looks like the .left elements are not only taking up the remaining space-- they're also taking up the entire row. Weirdly, the text inside these elements is centered as if it were only taking up the remaining space.
If you want the same to work for the buttons, it seems like the only solution involves a little hack. Buttons are quite complex indeed.
button.left {
margin: 0;
position: absolute; /*this seems to be the only way to get the button to stay on the same row - floating it left won't even work*/
z-index: -1; /*hides the "overflowing" part below the right button*/
width: 100%; /*make the button stretch to the full width of the row*/
padding-right: 400px; /*add a padding-right hack so that text will be centered correctly - should be same size as fixed width .right element*/
padding-left: 0;
display: block;
}
See updated fiddle: http://jsfiddle.net/wjFbD/6/
starting with
One element has fixed width, and the other element should take up
whatever width remains.
here is my general solution:
<div class="container">
<div class="two">125 €</div>
<div class="one">my favorite provider</div>
</div>
(stylus syntax, in your mind just add {,},;)
.one // red
border none
height auto
overflow hidden
white-space nowrap
text-overflow ellipsis
.two // green
float left
white-space nowrap
text-overflow ellipsis
You can set the one green thing to a fixed width, but indeed, you do not even have to! Things full up nicely. And String get's truncated with an ellipsis, if it gets too long.
Things get a bit more complicated, when one of them is a <button> rather than a <div> (and I can't figure out, which style property differenciates them, so I would need to style away), but anyway, with a wrapper, that also works:
→ See full codepen here. (Feedback appreciated.)