Since I'm new to flexbox, I can't find a way to get this layout work (or maybe it's impossible with flexbox).
Basically I want to have 3 columns: first one is the image, second is the H1 and description, and third is the button. The thing is I want the description to be able to expand underneath the button (the button should be on same row with the H1). Using float this is easy, but since I'm designing mobile first I want to use flexbox as much as possible. Can this be done with flexbox?
you can nest flexboxes. You'll need 3 nesting levels
Img + Text
In Text you'll have two units - Head + body
In Head you'll have two units - Title + button
<div class="flex">
<div>
<img src="#">
</div>
<div class="flex column">
<div class="flex head">
<h1>Title goes here</h1>
<button>Button</button>
</div>
<p>Lorem ipsum dolor sit amet</p>
</div>
live sample: http://codepen.io/anon/pen/mvzid?editors=110
I know this is old, This is another solution:
<div class="wrapper">
<div class="image-cont">
<img src="https://via.placeholder.com/150">
</div>
<div class="details-cont">
<h1>H1 title</h1>
<button type="button">Click Me!</button>
<p>long desription here... long description here... long description here</p>
</div>
</div>
CSS:
.wrapper {
display: flex;
}
.details-cont {
display: flex;
flex-wrap: wrap;
padding: 10px;
justify-content: center;
align-items: center;
}
p {
width: 100%;
margin: 0;
}
button {
margin-left: auto;
}
Related
So, I am creating a grid system based on flexbox and everything is going quite swimmingly. The basics of my grid are:
<div class="row">
<div class="column"><p>Column</p></div>
<div class="column"><p>Column</p></div>
<div class="column"><p>Column</p></div>
</div>
And in my css:
.row {
margin: 10px 0;
display: flex;
flex-wrap: wrap;
}
.column {
padding: 10px;
flex: 1 1 0%;
}
Essentially, this makes the columns quite fluid, and they shrink/grow to fill all available space. This is great for me as I need to use this throughout various projects where I can't quite customize the grid for every single one. However, I have run into a small "issue". I was going to create a class called ".collapse" so I could collapse the left/right padding to have some columns fit right next together (for example: If I wanted a div with a background color (by adding a color class to the column=> .column .green) flush to an image in the next column). However, the spacing is all out of wack compared to row/columns above it.
<div class="row">
<div class="column purple collapse"><p>Column</p></div>
<div class="column red collapse"><p>Column</p></div>
<div class="column purple collapse"><p>Column</p></div>
<div class="column red collapse"><p>Column</p></div>
</div>
example screenshot here
As you can see in my little example mockup, they do kinda line up, but the right and left margins have "decreased". Is there any smart way around this? I tried adding "left/right margins" to the first-of-type and last-of-type, but this just gets a bit hacky as then anything added in between start having odd alignment issues.
For this kind of grid system, you usually would discourage using structural styling on the grid cells directly, and it lets you do something like this:
.row {
display: flex;
flex-flow: row wrap;
list-style: none;
padding: 0;
margin-left: -10px;
}
.column {
flex: 1 0 0;
padding-left: 10px;
}
.collapse { margin-left: 0; }
.collapse > .column { padding-left: 0; }
.red,
.purple {
padding: 10px;
margin-bottom: 10px;
}
.red { background-color: red; }
.purple { background-color: purple; }
<div class="row">
<div class="column">
<div class="purple">
<p>Column</p>
</div>
</div>
<div class="column">
<div class="red">
<p>Column</p>
</div>
</div>
<div class="column">
<div class="purple">
<p>Column</p>
</div>
</div>
<div class="column">
<div class="red">
<p>Column</p>
</div>
</div>
</div>
<div class="row collapse">
<div class="column">
<div class="purple">
<p>Column</p>
</div>
</div>
<div class="column">
<div class="red">
<p>Column</p>
</div>
</div>
<div class="column">
<div class="purple">
<p>Column</p>
</div>
</div>
<div class="column">
<div class="red">
<p>Column</p>
</div>
</div>
</div>
This approach uses no margins on the outer ends, which I find way more convenient.
It's worth noting that this kind os system is not all that useful anymore, with the advent of CSS Grid Layout, but there you have it.
On a side note, 0 is always 0, and it never needs a unit.
What I want to have is two divs side-by-side and within one of them is an image and in the other is two divs, one above the other.
This happens to be a Wordpress theme, but I'm pretty sure this is basic CSS question.
The Wordpress stack exchange told me it was off-topic.
Call the left div #divL and the right div #divR.
I found an answer on SO mentioning that I should set display of #divL and #divR to
inline-block. I can get this to work on a test html file that I created in isolation but it doesn't work in the wordpress header. Specifically the divs in the wordpress header #divL and #divR act as if they had display: block rather than being positioned side-by-side.
Changing them to display: inline does put them side-by-side but then it
doesn't work to stack two divs within #divR.
I'll replicate here some of the code in the Wordpress header. Note that I'm going to simplify this by omitting the stacked divs inside #divR, because the symptom is obvious without that.
the following is what I'm using to try to get #divL and #divR to display side-by-side.
#divL { display: inline-block; }
#divR { display: inline-block; }
<header class="site-header">
<div class="wrap">
<div class="title-area">
<div id="divL">
<img id="logo-img" class="attachment-full size-full">
</div>
<div id="divR">Some text that should go on right</div>
</div>
<nav> .... </nav>
</div>
</header>
But they display one above the other.
Note that this actually does work to get them side-by-side, but then the
stacked divs inside #divR don't work as intended:
#divL { display: inline; }
#divR { display: inline; }
<header class="site-header">
<div class="wrap">
<div class="title-area">
<div id="divL">
<img id="logo-img" class="attachment-full size-full">
</div>
<div id="divR">Some text that should go on right</div>
</div>
<nav> .... </nav>
</div>
</header>
There is a lot of CSS on these other elements but I'm not sure which of it is important to this question so I'll wait for someone to comment and tell me what I should include.
As I wrote in my comment, you should set widths for those ìnline-blocks, that should basically do what you are after.
But as an alternative you can also use display: flex; on the container DIV. This can be done rather simple, but in the snippet below I added some additional settings to define a certain width for the two DIVs and to center the contents in these DIVs both horizontally and vertically (by also making the child elements flexboxes with flex-directon: column. For the rest of the settings see the code below.
.title-area {
display: flex;
justify-content: center;
align-items: stretch;
}
.title-area>* {
width: 40%;
border: 1px solid green;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
<header class="site-header">
<div class="wrap">
<div class="title-area">
<div id="divL">
<img id="logo-img" src="https://placehold.it/200x150/fa0" class="attachment-full size-full">
</div>
<div id="divR">Some text that should go on right</div>
</div>
<nav> .... </nav>
</div>
</header>
Here's an example of what would work:
<header class="site-header">
<div class="wrap">
<div class="title-area">
<div id="divL">
<img id="logo-img" class="attachment-full size-full" />
</div>
<div id="divR">
<div id="divTR">Some text that should go on top right</div>
<div id="divBR">Some text that should go on bottom right</div>
</div>
</div>
<nav>....</nav>
</div>
</header>
And the CSS:
#divL {
display: inline-block;
width: 49%;
}
#divR {
display: inline-block;
width: 49%;
}
But also Jon P is right; it might be worth your while to investigate one of the newer methods for dynamically spacing and sizing content.
I'm using Bulma have a column of cards which need to have the same height regardless of the content.
To achieve so I have created the following class
.equal-height
display: flex
flex-direction: column
height: 100%
My HTML looks like
<div class='columns is-multiline'>
<div class='column is-one-fifth'>
<div class='card equal-height'>
<div class='card-content'>
# CONTENT GOES HERE
</div>
<div class='card-footer'>
# FOOTER GOES HERE
</div>
</div>
</div>
<div class='column is-one-fifth'>
<div class='card equal-height'>
<div class='card-content'>
# CONTENT GOES HERE
</div>
<div class='card-footer'>
# FOOTER GOES HERE
</div>
</div>
</div>
</div>
Which produces something like
Now I'm trying to make the card-footer to stick at the bottom of the card like below.
I have tried a few things with flex but they don't really make sense.
Any ideas on how I may do it?
Add "flex: auto;" to '.card-contents' to make the card-footer to stick at the bottom of the card. Here is the working jsfiddle link.
.equal-height {
display: flex;
flex-direction: column;
height: 100%;
}
.equal-height .card-content {
flex: auto;
}
Add this CSS
.card-footer {
margin-top: auto;
}
working demo : https://jsfiddle.net/baLg7940/
UPDATE:
I made a fiddle for testing.
An illustration of what I'd like to achieve: (Rows and columns are Bootstrap 4 rows and columns.)
The page should only have scrollbars if the second row is already
"fully compressed" (0 height) and still the header + first row +
footer can't fit in the viewport.
The second row doesn't have to fill
in all remaining pale green place. It's height can be flexible.
Flexbox? Max-width? Overflow... How should I start? What could be a good solution?
HTML:
<div class="page">
<div class="header">
...<br>...
</div>
<div class="main">
<div class="container-fluid">
<div class="row">
<div class="col-6">
<div class="card">
<div class="card-header"> .... </div>
<div class="card-body"> .... </div>
</div>
</div>
<div class="col-6">
<div class="card">
<div class="card-header"> .... </div>
<div class="card-body"> .... </div>
</div>
</div>
</div>
<div class="row">
<div class="col-6">
<div class="card">
<div class="card-header"> .... </div>
<div class="card-body scrollable"> THIS <br> SHOULD <br> BE <br> THE <br> SCROLLABLE <br> CONTENT </div>
</div>
</div>
</div>
</div>
</div>
<div class="footer">
...
</div>
</div>
CSS:
div.page {
background-color: palegreen;
display: flex;
flex-direction: column;
min-height: 100vh;
max-height: 100vh;
}
div.header,
div.footer {
background-color: grey;
padding: 0.5em;
}
div.main {
display: flex;
flex-grow: 1;
}
div.row {
margin-top: 1em;
}
div.scrollable {
/* ??? */
}
The key is how you calculate the height for the <main> and usage of flex, esp. flex-grow, flex-shrink.
<header>, <main> and <footer>
The second row doesn't have to fill in all remaining pale green place. It's height can be flexible.
So I assume you want the <header> and <footer> always stay on top and bottom. Instead of regular absolute positioning approach, I want to explicitly set the heights for them, as well as for <main>.
HTML
<header>header</header>
<main class="container-fluid"></main>
<footer>footer</footer>
SCSS
$custom-header-height: 3rem;
$custom-footer-height: 2rem;
header, footer {
background-color: var(--gray);
// In order to position the text to the center, like your picture
display: flex;
flex-flow: row nowrap;
justify-content: center;
align-items: center;
}
header {
height: $custom-header-height;
}
footer {
height: $custom-footer-height;
}
main {
// Calculate the height for main, which is 100% viewport height -
// height of header - height of footer
height: calc(100vh - #{$custom-header-height} - #{$custom-footer-height});
background-color: var(--teal);
}
Result
This gives you the playground you can build stuff on.
First Row
The first row is free to expand as high as its contents, but you don't want it to take up any free space. That's why you set flex-grow: 0;. Also when you resize the window and the space for first row is shrinking, you don't want the cards go over the row. That's why you set flex-shrink: 0;. We might as well use the shortcut flex: 0 0 auto; for those 2.
But in order to set that, the first row (as well as the second row) needs to be flexbox children. So we set display:flex; on its parent - <main>.
HTML
<header>header</header>
<main class="container-fluid">
<div class="row first-row">
<div class="col-6">
<div class="card">...</div>
</div>
<div class="col-6">
<div class="card">...</div>
</div>
</div>
</main>
<footer>footer</footer>
SCSS (In addition)
main {
display: flex;
flex-flow: column nowrap;
}
.first-row {
// I purposely make first row's background yellow so that you can see it
background-color: var(--yellow);
flex: 0 0 auto;
}
Result
Second Row
The key here is to make the <card> not to grow when there is space, but shrink on limited space, which is the default of flexbox children: flex: 0 1 auto;
But again, in order to use that, its parent needs to display: flex;. Here the parent is col-6 since we want to use bootstrap grid system.
HTML
<header>header</header>
<main class="container-fluid">
<div class="row first-row">
<div class="col-6">
<div class="card">...</div>
</div>
<div class="col-6">
<div class="card">...</div>
</div>
</div>
<div class="row second-row">
<div class="col-6">
<div class="card">
...
...
...
</div>
</div>
</div>
</main>
<footer>footer</footer>
SCSS (In addition)
.second-row {
// I purposely make second row's background to be blue so that you can see it
background-color: var(--blue);
// Any column, class name starts as "col-"
[class*="col-"] {
display: flex;
flex-flow: column nowrap;
// So that when the second row is compressed to 0, it doesn't show
// the row completely.
min-height: 0;
.card {
// flex-grow: 0;
// flex-shrink: 1;
// Might as well just set it
// flex: 0 1 auto;
// But this is the default of flexbox children so we don't need to set
// it here.
.card-body {
overflow-y: auto;
}
}
}
}
Result
The second row doesn't have to fill in all remaining pale green place. It's height can be flexible.
An illustration of what I'd like to achieve
The page should only have scrollbars if the second row is already "fully compressed" (0 height) and still the header + first row + footer can't fit in the viewport
Notes
There is still a funkiness when the second row is fully compressed. The scrollbar is still hanging there and I don't know how to get rid of it.
The code can be simplified a little bit without usage of bootstrap grid system.
Demo
https://codepen.io/anon/pen/XBqyxZ
Sorry for this lengthy post. If you want to know more about flexbox, here is a great guide: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
I would but a set the height (or max-height if you prefer) on the card and then set overflow to scroll.
<html>
<div class="box">
<div class="content">
Dispassionate extraterrestrial observer citizens of distant epochs
permanence of the stars billions upon billions vastness is bearable only
through love brain is the seed of intelligence.
</div>
</div>
</html>
<style>
.box {
width: 500px;
overflow: scroll;
}
</style>
I am trying to have an image sitting next to some text. The text needs to sit halfway vertically on the image
[IMG]
[IMG] Here is the text
[IMG]
I am getting the following, because the two cell divs are equal width, instead of matching content width:
[IMG]
[IMG] Here is the text
[IMG]
The code is preexisting. There is a table container div:
.vertical-align-container {
display: table;
table-layout: auto;
width: 100%;
}
And two table cell divs:
.vertical-align-child {
display: table-cell;
vertical-align: middle;
padding-left: 15px;
}
So no matter what I do, the table cells are equal width. How can I get the first to match content width, and the second to fill the remainder of the container?
HTML:
<div class="vertical-align-container">
<div class="vertical-align-child" style="padding-left: 0;">
<img src="path/img.png">
</div>
<div class="vertical-align-child">
<p>Here is the text</p>
</div>
</div>
As you can see, I've tried a couple things, but what I've included here is table-layout, which I though was supposed to do exactly this?
I think you could approach this with flexbox.
You can use the align-items property for vertical centering.
.container,
.text {
display: flex;
}
.text {
align-items: center;
padding-left: 1rem;
}
.image img {
display: block;
width: 100%;
height: auto;
}
<div class="container">
<div class="image">
<img src="https://unsplash.it/200">
</div>
</div>
<div class="container">
<div class="image">
<img src="https://unsplash.it/200">
</div>
<div div class="text">
<p>
Here is the text
</p>
</div>
</div>
<div class="container">
<div class="image">
<img src="https://unsplash.it/200">
</div>
</div>
Found an ugly workaround for this here:
CSS table column autowidth
The issue I was having was that my image is set to 100% width, while using a max-width of the size I wanted it to stop at. Apparently the table isn't willing to read in the max-width as the content size, so it chose 50%.
I hacked in a width for the image and set the table cell to have nowrap, as in the linked question. It's not by any means a good answer, but it'll do for a quick fix.