I have some slides where I'm trying to equally space content using display: flex but it's adding a large empty area below my content and above the navigation.
When the screen shrinks to the mobile size the empty area becomes much more apparent.
I have no idea why it's doing this, or why switching display: flex to display:table messes things up even more.
After spending two days I've come for some guidance.
Here's a test link to what I have. Click on 1 - 4 to get to a screen using flex.
<div class="slide" id="slide-one" data-slide="1">
<p class="deck">You don’t have to wait until bad weather is imminent to prepare for a power outage. Take some time to get organized with these tips.</p>
<div class="row">
<div class="section" id="emergency-kit">
<div class="rollover center">
<div class="button-container">
<div class="button"></div>
</div>
<div class="text">Create an Emergency Kit</div>
</div>
<div class="container">
<img src="img/emergency-kit.png" alt="" />
</div>
</div>
<div class="section" id="food-prep">
<div class="rollover center">
<div class="button-container">
<div class="button"></div>
</div>
<div class="text">Prep Your Food</div>
</div>
<div class="container">
<img src="img/fridge.png" alt="" />
</div>
</div>
</div>
</div>
.row {
display: flex;
width:100%;
flex-direction: row;
margin-top: 20px;
}
#emergency-kit {
width:40%;
display: inline-block;
.container {
max-width: 263px;
}
}
#food-prep {
width:40%;
display: inline-block;
.container {
max-width: 167px;
}
}
Also, using flexslider for the slideshow animations.
The source of the gap has nothing to do with flexbox. Your flex container (.row) is nested within a larger container.
div.row
... is a descendant of div.flex-viewport
... which takes up all the height to the bottom navbar.
On the smaller screen, div.row isn't even a flex container anymore. It's switched to a block element:
Possible options for closing the gap:
Reduce the height of one of the containers
Define heights for all container elements between .flex-viewport and .row
Apply display: flex to all containers, so children can expand the full height of their parent
Related
I have no idea why my website cannot display to change flex (I mean, some element of text on the left side and the images on the right side), why it's not working?
.presentation {
display: flex;
width: 90%;
margin: auto;
min-height: 80vh;
align-items: center;
}
.introduction {
flex: 1;
}
.cover img {
height: 60vh;
}
<main>
<section class="presentation">
<div class="introduction">
<!--intro text..., -->
<div class="intro-text">
<h1>mac</h1>
<p>This is the latest laptop and this laptop is the best ever until nobody doubt that want to mac. This is very powerfull, strong and almost 8k</p>
</div>
<!--button ...,-->
<div class="cta">
<button class="cta-select">14-inch</button>
<button class="cta-add">Add Cart</button>
</div>
<!-- and images of laptop -->
<div class="cover">
<img src="https://bhrigu.me/images/mac.png" alt="laptop mac">
</div>
</div>
</section>
</main>
You have mistakenly used flex property in root directory. Which elements you want to apply flex property/display, you have to use flex property immediate on parent div.
For example:
You have to put flex on intro-text class.
CSS:
.intro-text {
display: flex;
}
<div class="intro-text">
<!--button ...,-->
<div class="cta">
<button class="cta-select">14-inch</button>
<button class="cta-add">Add Cart</button>
</div>
<!-- and images of laptop -->
<div class="cover">
<img src="https://bhrigu.me/images/mac.png" alt="laptop mac">
</div>
</div>
And if you want to place an element in the right position. Just use
.cover {
margin-left: auto;
}
Please take a look here:
https://codepen.io/ilazycoder/pen/jOWQvYj
I've been doing some stuff with HTML and I need to have a few columns. I know how to make them and the basics of how they work. However, there is a certain problem that I have. I need to have 3 columns that have an image on top, then text on bottom. However, the text on bottom can't flow into the next column if the browser is resized - it just needs to go up or down. What I have so far:
body {
background-color: white;
font-family: times, serif;
color: black;
}
div {
display: flex;
margin: 50px;
flex-wrap: wrap;
}
<div>
<div class="first">
<img src="Images/australia_flag.jpg" alt="Australian Flag" title="Australian Flag" height="200" width="300"> text as well </div>
<div class="second">
<img src="Images/brazil_flag.jpg" alt="Brazilian Flag" title="Brazilian Flag"> even more text </div>
<div class="third">
<img src="Images/china_flag.jpg" alt="Chinese Flag" title="Chinese Flag" height="200" width="300"> text again
</div>
</div>
not entirely sure if you mean columns or rows? Based on your code, it looks like rows. If that's the case, I'm not sure what you mean by "flow into the next column"? You might check out the relative and absolute values for CSS position.
If, in fact, you do actually mean columns, I'd strongly advise using Bootstrap's Grid System. This is great for creating responsive columns.
Please take a look at this simple 3 column layout with a full width content area on top and bottom here: https://jsfiddle.net/7drfva0o/2/
.top, .bottom {
width:98%;
padding:1%;
background-color: red;
clear:both;
}
.cols {
width:31%;
padding:1%;
float:left;
background-color:blue;
border: 1px solid #FFF;
}
Is that what you're looking for?
First, you'll need to improve your markup: having images and texts as DOM node to be "flexed"
HTML markup improved
<div class="wrapper">
<div class="column">
<img src="..." />
<p>text</p>
</div>
<div class="column">
<img src="..." />
<p>text</p>
</div>
<div class="column">
<img src="..." />
<p>text</p>
</div>
</div>
Then, each of your div is going to have display: flex + flex-direction: column to allow the image going on top and the text going below. You will be able to adjust margin or whatever. At the minimum, I'd go like this:
CSS improved
.wrapper {
display: flex;
}
.column {
margin: 5px;
display: flex;
flex-direction: column;
}
Wrapped altogether, here is a snippet of what I think you're trying to achieve
Snippet
.wrapper {
display: flex;
}
.column {
margin: 5px;
display: flex;
flex-direction: column;
}
<div class="wrapper">
<div class="column">
<img src="http://fakeimg.pl/300x200" />
<p>text as well</p>
</div>
<div class="column">
<img src="http://fakeimg.pl/300x200" />
<p>text as well</p>
</div>
<div class="column">
<img src="http://fakeimg.pl/300x200" />
<p>text as well</p>
</div>
</div>
Then, feel free to play with flexbox properties to align, wrap, adjust alignments, etc. Great documentation on CSS-Tricks : https://css-tricks.com/snippets/css/a-guide-to-flexbox/
I've seen fixes for individual parts of this problem but not one for a collective solution. I can solve everything without resorting to javascript formatting except for margins from elements being carried over to the top of the next column (I can't understand why it hasn't been fixed but it appears to be a bug in css3 for some time that's impeding compositing layouts 1, 2)
I've a responsive div container broken into three columns (though this can change depending on the width of the page, per responsive layout), containg divs with a varying number of nested images of varying aspect ratios that each have a margin-bottom property. The above problem is very apparent so I'm looking for a solution to this.
Typically the suggestion involves the use of a column-break-inside: avoid; property alongside switching my margin-bottom to padding-bottom. This hack has seen some success with others and this is where I point you to the subject of my question. I cannot implement this as I'm using a seperate hack to prevent reflow of images that are lazy loaded (using the lazy sizes plugin*) into the columns (the padding-bottom as a ratio hack, 3).
So if I use padding-bottom to ensure that my column elements align without orphaned margins, I lose the ability to correct the reflow from lazy loading the elements into the columns. I can't use fixed sized elements as the column layout is responsive and the elements shrink and enlarge dynamically with the column size.
Is there anybody who has succeeded in solving both issues simultaneously without javascript formatting?
I'm keen to stick to this particular lazy loading plugin for reasons outside of the scope of this problem.
HTML Code:
<div id='columncontainer'>
<div class='imagecontainer' style='padding-bottom:reflowPaddingAmountFromPHPvar;'>
<img class='lazyload'>
<div class='imagetextcontainer'>
<div class='vertaligncontainer'>
<p class='imagename'>Text</p>
<p class='imagedesc'>Text</p>
</div>
</div>
</div>
</div>
CSS Code:
#myContent {
position: relative;
width: 100%;
column-count: 3;
column-gap: 20px;
column-break-inside: avoid;
-moz-column-break-inside:avoid;
-webkit-column-break-inside:avoid;
}
.imagecontainer {
position: relative;
margin-bottom: 20px;
img {
position: absolute;
top: 0;
left: 0;
height: auto;
width: 100%;
}
}
Example jsFiddle:
https://jsfiddle.net/g0yjd9ov/1/
The elements should align at the top of each column but, instead, the margin-bttom on the element (imagecontainer) at the bottom of the first or second column is being carried over to the second or third column and orphaned, giving the impression of the next element having a margin-top value and breaking the top alignment. This serves no benefit to any situation that a deliberate margin-top value couldn't recreate. I've randomised the heights of the elements just for this example, so occasionally the problem won't show (emphasising how much of a nuisance it is. It's hard to deliberately show). Just refresh if it doesn't, as it occurs quite frequently.
This can be solved using an extra container that has padding on it. The container for the image (.imagecontainer) should contain only the image, as that is what its aspect ratio is set up for. The space between a block and the next block in the column can be achieved by setting a padding on that block. The block then gets the styling that prevents column breaks from occurring.
I have created a demo that builds upon the example code in the question, but also includes some things that are only described in the question text. This because I wanted to make sure that everything works the way I think it should (let me know if I misinterpreted the question).
In particular, I added the lazy sizes plugin and let it load some placeholder images. I also added some styling and added blocks that contain more than just a single image. For the rules that prevent breaks inside an element, I used some slightly different ones, as per this answer. Finally, I positioned the .imagetextcontainer as discussed in the question comments.
The demo can be found on JSFiddle. I also include it as a code snippet here.
#columncontainer {
width: 100%;
column-count: 3;
column-gap: 10px;
}
.block-wrap {
width: 100%;
padding-bottom: 10px;
/* prevent column breaks in item
* https://stackoverflow.com/a/7785711/962603 */
-webkit-column-break-inside: avoid; /* Chrome, Safari */
page-break-inside: avoid; /* Theoretically FF 20+ */
break-inside: avoid-column; /* IE 11 */
display:table; /* Actually FF 20+ */
}
.block {
width: 100%;
background-color: #ffff7f;
}
.block > p {
margin: 0;
padding: 10px;
}
.imagecontainer {
position: relative;
width: 100%;
height: 0;
background-color: #a00;
}
.imagecontainer > img {
width: 100%;
}
.imagetextcontainer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
<script src="https://afarkas.github.io/lazysizes/lazysizes.min.js"></script>
<div id='columncontainer'>
<div class="block-wrap">
<div class="block">
<div class='imagecontainer' style='padding-bottom: 50%;'>
<img class='lazyload'
data-sizes='auto'
data-srcset='https://placehold.it/100x50/a00/fff 100w,
https://placehold.it/200x100/050/fff 200w,
https://placehold.it/400x200/057/fff 400w' />
<div class='imagetextcontainer'>
<div class='vertaligncontainer'>
<p class='imagename'>Name</p>
<p class='imagedesc'>Description</p>
</div>
</div>
</div>
<p>Some text. Followed by another figure.</p>
<div class='imagecontainer' style='padding-bottom: 100%;'>
<img class='lazyload'
data-sizes='auto'
data-srcset='https://placehold.it/100x100/a00/fff 100w,
https://placehold.it/200x200/050/fff 200w,
https://placehold.it/400x400/057/fff 400w' />
<div class='imagetextcontainer'>
<div class='vertaligncontainer'>
<p class='imagename'>Name</p>
<p class='imagedesc'>Description</p>
</div>
</div>
</div>
</div>
</div>
<div class="block-wrap">
<div class="block">
<div class='imagecontainer' style='padding-bottom: 50%;'>
<img class='lazyload'
data-sizes='auto'
data-srcset='https://placehold.it/100x50/a00/fff 100w,
https://placehold.it/200x100/050/fff 200w,
https://placehold.it/400x200/057/fff 400w' />
<div class='imagetextcontainer'>
<div class='vertaligncontainer'>
<p class='imagename'>Name</p>
<p class='imagedesc'>Description</p>
</div>
</div>
</div>
<p>Some text. No figure here.</p>
</div>
</div>
<div class="block-wrap">
<div class="block">
<p>Only text here.</p>
</div>
</div>
<div class="block-wrap">
<div class="block">
<div class='imagecontainer' style='padding-bottom: 50%;'>
<img class='lazyload'
data-sizes='auto'
data-srcset='https://placehold.it/100x50/a00/fff 100w,
https://placehold.it/200x100/050/fff 200w,
https://placehold.it/400x200/057/fff 400w' />
<div class='imagetextcontainer'>
<div class='vertaligncontainer'>
<p class='imagename'>Name</p>
<p class='imagedesc'>Description</p>
</div>
</div>
</div>
</div>
</div>
<div class="block-wrap">
<div class="block">
<div class='imagecontainer' style='padding-bottom: 100%;'>
<img class='lazyload'
data-sizes='auto'
data-srcset='https://placehold.it/100x100/a00/fff 100w,
https://placehold.it/200x200/050/fff 200w,
https://placehold.it/400x400/057/fff 400w' />
<div class='imagetextcontainer'>
<div class='vertaligncontainer'>
<p class='imagename'>Name</p>
<p class='imagedesc'>Description</p>
</div>
</div>
</div>
</div>
</div>
<div class="block-wrap">
<div class="block">
<p>Only text here.</p>
<p>Tow lines now.</p>
</div>
</div>
<div class="block-wrap">
<div class="block">
<div class='imagecontainer' style='padding-bottom: 200%;'>
<img class='lazyload'
data-sizes='auto'
data-srcset='https://placehold.it/100x200/a00/fff 100w,
https://placehold.it/200x400/050/fff 200w,
https://placehold.it/400x800/057/fff 400w' />
<div class='imagetextcontainer'>
<div class='vertaligncontainer'>
<p class='imagename'>Name</p>
<p class='imagedesc'>Description</p>
</div>
</div>
</div>
</div>
</div>
</div>
After a lot of back and forth I came up with an answer that fixes the problem and maintains the original's CSS properties. There seems to have been two problems causing this.
1 - margins were translating into the next column (but the element was staying into its own column)
2 - height was confined (was a problem in the solution)
solution: since the entire element stays in its own column but the margin is technically not part of the element (it can be tested using outline)
this problem can be solved by placing .imagecontainer into another div which has padding instead of margin. (so then its considered one object so the margin problem is avoided)
you also would need to move column-break-inside to the parent element so it registers without the margin.
a live version can be found at: https://jsfiddle.net/36pqdkd3/6/
Here is a solution using flex-boxes
HTML
<div id='columncontainer'>
<div class='imagecontainer'>
<img class='lazyload'>
<div class='imagetextcontainer'>
<div class='vertaligncontainer'>
<p class='imagename'>Text</p>
<p class='imagedesc'>Text</p>
</div>
</div>
</div>
<div class='imagecontainer'>
<img class='lazyload'>
<div class='imagetextcontainer'>
<div class='vertaligncontainer'>
<p class='imagename'>Text</p>
<p class='imagedesc'>Text</p>
</div>
</div>
</div>
<div class='imagecontainer'>
<img class='lazyload'>
<div class='imagetextcontainer'>
<div class='vertaligncontainer'>
<p class='imagename'>Text</p>
<p class='imagedesc'>Text</p>
</div>
</div>
</div>
<div class='imagecontainer' style=''>
<img class='lazyload'>
<div class='imagetextcontainer'>
<div class='vertaligncontainer'>
<p class='imagename'>Text</p>
<p class='imagedesc'>Text</p>
</div>
</div>
</div>
</div>
CSS
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
#columncontainer {
position: relative;
width: 100%;
display: flex;
height: 40%;
/* use this if you want containter wrapping
flex-wrap: wrap; */
/* use this if you want container scrolling
overflow: auto; */
/* use this if you want container scrolling
justify-content: center; */
}
.imagecontainer {
min-width: 250px;
position: relative;
background-color: red;
overflow: hidden;
height: 100%;
margin: 5px;
z-index: 1;
}
example in jsfiddle
Here are some recommendations based on your question.
I would also recommend learning more about flex-boxes, that is very equipped to handle these kinds of situations.
by default the html and body elements default size is width 100% and no height.
here is a reference I use on flex-boxes
addressing aspect ratio
you can handle aspect ratio using px and vw/vh (measurements of DOM width and height). try playing around with min/max/width to find the perfect amount.
(1:2 aspect ratio)
element {
min-width: 10vw;
min-height: 20vh;
width: 50px;
height: 100px;
}
css size units
in my version you can edit ".imagecontainer".
I'm pretty new to HTML and CSS so perhaps this is a crazy easy question to answer.
The question is:
How to do this using only divs and css?
I don't want to use <table> <tr> <th> <td>....
Here's a basic setup of what you're asking using the flexbox property.
The CSS3 Flexible Box, or flexbox, is a layout mode providing for the
arrangement of elements on a page such that the elements behave
predictably when the page layout must accommodate different screen
sizes and different display devices. For many applications, the
flexible box model provides an improvement over the block model in
that it does not use floats, nor do the flex container's margins
collapse with the margins of its contents.
Read more about it at MDN and experiment with it so you feel comfortable using it. The setup might not be pixel perfect, but it gives you a good start for the desired layout. Trial and error, that's the best way to learn.
div {
box-sizing: border-box;
border: 1px solid black;
min-height: 20px;
}
.container {
display: flex;
flex-flow: row-wrap;
width: 100%;
}
.column {
flex: 1 1 100%;
}
.middle {
flex-basis: 200%;
}
.middle-top,
.right-top,
.right-bottom {
display: flex;
flex-flow: row wrap;
width: 100%;
}
.language,
.search,
.login,
.signup,
.some-text,
.avatar {
flex: 1 1 50%;
}
<div class="container">
<div class="column left">
<div class="social">
Social icons
</div>
<div class="logo">
Logo
</div>
</div>
<div class="column middle">
<div class="middle-top">
<div class="language">
Language
</div>
<div class="search">
Search
</div>
</div>
<div class="slogan">
Slogan
</div>
<div class="menu">
Menu
</div>
</div>
<div class="column right">
<div class="right-top">
<div class="login">
Login
</div>
<div class="signup">
Signup
</div>
</div>
<div class="right-middle">
Welcome guest
</div>
<div class="right-bottom">
<div class="some-text">
<div class="something">
Some text
</div>
<div class="something">
Some text
</div>
</div>
<div class="avatar">
Avatar
</div>
</div>
</div>
</div>
The desired display is to have the text in the left column vertically centered (middle). I have not been able to achieve that. This is because the picture in the right column is taller than the 2 paragraphs of text. Interestingly, the orange div is only as high as the paragraphs.
The inline styles are only there for debug.
The design being used is responsive so I'm assuming setting a height in px will make it non-responsive.
Edit: The inline debug styles were misleading so have been removed
<div class="row">
<div class="col-md-8">
<div class="vertical-align-center">
<p>First small paragraph with other elements in it</p>
<p>Second small paragraph with other elements in it</p>
</div>
</div>
<div class="col-md-4">
<img class="img-responsive img-md-size" src="blog.localhost/klequis/wp-content/uploads/2016/0521/DevBoxRunning.png">
</div>
</div>
In Bootstrap 4 and above, you can add the align-self-center class to the column div to vertically center it.
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" />
<div class="row">
<div class="col-8 align-self-center">
<p>First small paragraph with other elements in it</p>
<p>Second small paragraph with other elements in it</p>
</div>
<div class="col-4">
<img src="//lorempixel.com/150/300/" class="img-responsive" />
</div>
</div>
Edited Answer
If you want for the two things to be the same height, you're running into a problem that has existed since float became a thing. This Stackoverflow Question is from 2009 and it's about the same thing. You can choose to use the method described in that post, which basically equates to setting the bottom margin to some crazy huge number in order to pull the bottom edge down but that gets hidden with a overflow div, like so. Unfortunately, this doesn't net you a vertical center on the text since the thing that's actually stretching all that height is the margin/padding of the box, not the inner height.
.vertical-align-center {
display: table;
height: 100%;
width: 100%;
}
.vertical-align-center .valign-center {
display: table-cell;
vertical-align: middle;
height: 100%;
}
.vertical-align-center > div {
padding-bottom: 200em;
margin-bottom: -200em;
}
.overflow-hidden {
overflow: hidden;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<div style="background-color:blue;" class="row overflow-hidden">
<div style="background-color:orange; height:1000px;" class="col-xs-8 vertical-align-center">
<div style="background-color: green;" class="valign-center">
<p>First small paragraph with other elements in it</p>
<p>Second small paragraph with other elements in it</p>
</div>
</div>
<div class="col-xs-4">
text
</div>
</div>
Alternate
Now the next part is for display:flex, something more uncommon, and it isn't fully supported by all mainstream browsers yet. According to Can I Use a good chunk of browsers can use it, but for things like IE it's going to be buggy.
NOTE: This is going to override bootstrap's display:float and it may not be exactly what you would like to see. I will leave it to you to figure out the spacing. CSS Tricks has a really nice side-by-side for the flex-container and the flex-items.
.row.flex-override {
display: -ms-flex;
display: -webkit-flex;
display: flex;
justify-content: space-around;
}
.row.flex-override > .vertical-align-center {
display: -ms-flex;
display: -webkit-flex;
display: flex;
}
.row.flex-override .vertical-align-center .valign-center {
align-self: center;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<div class="row flex-override">
<div class="col-xs-8 vertical-align-center" style="background-color: green;">
<div class="valign-center">
<p>First small paragraph with other elements in it</p>
<p>Second small paragraph with other elements in it</p>
</div>
</div>
<div class="col-xs-4" style="background-color:orange;">
<img src="//lorempixel.com/500/500/cats/1" class="img-responsive" />
</div>
</div>
Original Answer
You had a few random little errors in your code, the biggest of which was you put height=100% in the inline style. It should read height:100%
Note: you don't really need the valign-center class, but it makes it a little bit more readable in my opinion.
Happy Coding.
.vertical-align-center {
display: table;
height: 100%;
width: 100%;
}
.vertical-align-center .valign-center {
display: table-cell;
vertical-align: middle;
height: 100%;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<div style="background-color:blue;" class="row">
<div style="background-color:orange; height:1000px;" class="col-xs-8 vertical-align-center">
<div style="background-color: green;" class="valign-center">
<p>First small paragraph with other elements in it</p>
<p>Second small paragraph with other elements in it</p>
</div>
</div>
<div class="col-xs-4">
text
</div>
</div>