The image below shows my currently layout where the height of container 1 and 3 is determined by the middle column. In my mobile view, I want the containers to stack on top of each other, that is, 1,2,3,4. However with my current approach, I have 1,2,4,3
<div class="wrapper">
<div class="aside aside-1">
<h2>container 1</h2>
</div>
<div class="main">
<div class="inner-content first">
<h2>container 2</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque id fermentum erat, cursus viverra risus. Cras sodales risus justo, in pretium eros pretium ut.</p>
</div>
<div class="inner-content last">
<h2>container 4</h2>
</div>
</div>
<div class="aside aside-2">
<h2>container 3</h2>
</div>
</div>
.wrapper {
display: flex;
flex-flow: row wrap;
}
.wrapper > * {
flex: 1 100%;
margin: 20px 0;
}
.main {
margin-right: 20px;
margin-left: 20px;
.inner-content {
background: yellow;
padding: 10px;
&.first {
margin-bottom: 20px;
}
}
}
.aside-1, .aside-2 {
background: yellow;
padding: 10px;
}
#media all and (min-width: 600px) {
.aside { flex: 1 0 0; }
}
#media all and (min-width: 800px) {
.main { flex: 1 0px; }
.aside-1 { order: 1; }
.main { order: 2; }
.aside-2 { order: 3; }
.footer { order: 4; }
}
Here is a link to demonstrate issue
display: contents;
With your actual markup, one of the soution would be to use display: contents; on .main div.
These elements don't produce a specific box by themselves. They are replaced by their pseudo-box and their child boxes. Please note that the CSS Display Level 3 spec defines how the contents value should affect "unusual elements" — elements that aren’t rendered purely by CSS box concepts such as replaced elements.
Source: MDN.
Two caveats:
It might remove the content from the accessibility tree
It's not supported by IE
Snippet as follows :
.wrapper {
display: flex;
flex-flow: row wrap;
}
.wrapper > * {
flex: 1 100%;
margin: 20px 0;
}
.main {
margin-right: 20px;
margin-left: 20px;
display: contents;
.inner-content {
background: yellow;
padding: 10px;
&.first {
margin-bottom: 20px;
}
}
}
.aside-1,
.aside-2 {
background: yellow;
padding: 10px;
}
.last {
order: 2;
}
.aside-2, .last {
width: 100%;
margin: 20px 0;
}
#media all and (min-width: 600px) {
.aside {
flex: 1 0 0;
}
}
#media all and (min-width: 800px) {
.main {
flex: 1 0px;
display: block;
}
.aside-1 {
order: 1;
}
.main {
order: 2;
}
.aside-2 {
order: 3;
}
.last {
width: auto;
}
}
<div class="wrapper">
<div class="aside aside-1">
<h2>container 1</h2>
</div>
<div class="main">
<div class="inner-content first">
<h2>container 2</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque id fermentum erat, cursus viverra risus. Cras sodales risus justo, in pretium eros pretium ut.</p>
</div>
<div class="inner-content last">
<h2>container 4</h2>
</div>
</div>
<div class="aside aside-2">
<h2>container 3</h2>
</div>
</div>
Support:
Table of support on Can I Use
css grid
By changing your actual markup and using grid, you could have an easier solution.
There is many ways to do it and I would adjust the HTML markup depending on the importance of the content for the page.
A solution would be to have a wrapper with for children as follows : Content 1, Content 2, Content 3, Content 4.
On mobile, you can keep the initial box model display: block; and make the adjustement only in your media queries.
Snippet as follows :
.wrapper > div {
background: yellow;
padding: 10px;
margin-bottom: 20px;
}
#media all and (min-width: 800px) {
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: auto auto;
gap: 20px 20px;
grid-template-areas:
"aside-1 first aside-2"
"aside-1 last aside-2";
}
.aside-2 { grid-area: aside-2; }
.aside-1 { grid-area: aside-1; }
.first { grid-area: first; }
.last { grid-area: last; }
.wrapper > div {
margin-bottom: 0;
}
}
<div class="wrapper">
<div class="aside-1">
<h2>container 1</h2>
</div>
<div class="first">
<h2>container 2</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque id fermentum erat, cursus viverra risus. Cras sodales risus justo, in pretium eros pretium ut.</p>
</div>
<div class="aside-2">
<h2>container 3</h2>
</div>
<div class="last">
<h2>container 4</h2>
</div>
</div>
The markup and the styles are simpler than your initial code: less div and less rules.
Table of support on Can I Use
Don't forget to prefix your rules whe you use grid.
Related
I'm trying to make a div with some children inside always fit to the parent div which covers the whole page. It already works that the child div's width fits into the parent's. But the height should also fit inside the parent div. I want to avoid using overflow: auto because then the user will have to scroll in some cases. The child div (with it's children inside) should always fit in the parent's height and width.
How can I make this in CSS?
<div class="parent">
<div class="child">
<button>Toggle</button>
<img />
<p>Some text here...</p>
</div>
</div>
The <div class="parent"> covers the whole page. The <div class="child"> should scale into the <div class="parent"> width and height.
You can try this. You would need a media query for mobile but does what I think you are asking...
<html>
<head>
<style>
body {
font-weight: 400;
background-color: black;
color: white;
font-family: sans-serif;
margin: 0;
}
.grid {
min-height: 100%;
grid-column: 1 / -1;
grid-gap: 0;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(33%, 1fr));
}
.grid>span {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
}
.image {
background-image: url('https://live.staticflickr.com/7206/6859864719_5d68aedbd7.jpg');
background: cover;
background-position: center center;
background-repeat: no-repeat;
}
.toggle {
background: #4096C0;
border-radius: 2px;
padding: 12px 24px;
color: white;
width: auto;
text-align: center;
cursor: pointer;
}
.toggle:hover {
background: #00537C;
}
.text {
background: #40B6C0;
padding: 72px;
color: white;
}
</style>
</head>
<body>
<div class="container">
<div class="grid">
<span class="toggle">TOGGLE</span>
<span class="image"></span>
<span class="text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam eu fermentum dolor. Cras aliquet tempus elit ut eleifend. In commodo malesuada nisi non vulputate.</span>
</div>
</div>
</body>
</html>
I have a image that I would like to shrink in a flexbox column layout. I have read a bunch of pertinent threads but I still can't figure it out.
I want the right column to always have the same height of the left column and the image in the right column to fill the height of the remaining space not taken up by the text. Any thoughts? Thank you!
I would like it to look like this:
Codepen here: https://codepen.io/interzonestudio/pen/qBRPxzg
This is my HTML:
<div class="block-one">
<div class="block-one-left">
<img src="https://via.placeholder.com/300x400" alt="">
</div>
<div class="block-one-right">
<div class="block-one-right-top">
<img src="https://via.placeholder.com/300x400?text=Shrink+Me!" alt="">
</div>
<div class="block-one-right-bottom">
<p>Lorem ipsum dolor sit amet, consectetuer diiscing elit, sed diam nonummy nibh dolor it euismod tincidunt ut laoreet dolore.</p>
</div>
</div>
</div>
and this is my CSS:
.block-one {
width: 50%;
padding: 50px;
background: #9ac1e4;
margin: 0 50px 100px 50px;
display: flex;
min-height: 0;
min-width: 0;
max-width: 100%;
max-height: 100%;
}
.block-one-left {
width: 40%;
padding-right: 50px;
}
.block-one-left img {
width: 100%;
}
.block-one-right {
width: 60%;
display: flex;
flex: 1;
flex-direction: column;
}
.block-one-right-top {
height: 100%;
flex: 1;
}
.block-one-right-top img {
height: 100%;
max-width: 100%;
max-height: 100%;
min-height: 0;
min-width: 0;
width: auto;
object-fit: contain;
}
You can achieve this with a tiny piece of javascript to calculate the difference of left img height minus text height and set the right image height to that difference. Just place these 4 lines javascript in a <script></script>-tag just before the closing body tag.
Working example:
var max_height = document.querySelector('.block-one-left').clientHeight;
var text_height = document.querySelector('.block-one-right-bottom').clientHeight;
var shrink_height = max_height - text_height;
document.querySelector('.block-one-right-top').style.height = shrink_height + 'px';
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.block-one {
display: flex;
width: 600px;
margin: 0 50px 100px 50px;
padding: 25px;
background: #9ac1e4;
}
.block-one-left {
height: 300px;
margin-right: 25px;
}
.block-one-left img {
height: 100%;
}
.block-one-right {
width: 225px;
}
.block-one-right-top img {
height: 100%;
}
.block-one-right-bottom {
padding-top: 25px;
}
<div class="block-one">
<div class="block-one-left">
<img src="https://via.placeholder.com/300x400" alt="">
</div>
<div class="block-one-right">
<div class="block-one-right-top">
<img src="https://via.placeholder.com/300x400?text=Shrink+Me!" alt="">
</div>
<div class="block-one-right-bottom">
<p>Lorem ipsum dolor sit amet, consectetuer diiscing elit, sed diam nonummy nibh dolor it euismod tincidunt ut laoreet dolore.</p>
</div>
</div>
</div>
If you want it to be responsive you have to wrap the 4 lines in a function. Because you have to listen for at least two events (image loaded and window resized) it is much cleaner to call the function instead of having the 4 lines twice in your code.
Working example:
var left_img = document.querySelector('.block-one-left img');
function setHeight() {
var max_height = left_img.clientHeight;
var text_height = document.querySelector('.block-one-right-bottom').clientHeight;
var shrink_height = max_height - text_height;
document.querySelector('.block-one-right-top').style.height = shrink_height + 'px';
}
left_img.addEventListener('load', setHeight);
window.addEventListener('resize', setHeight);
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.block-one {
display: flex;
width: 100%;
padding: 25px;
background: #9ac1e4;
}
.block-one-left {
width: 40%;
margin-right: 25px;
}
.block-one-left img {
width: 100%;
}
.block-one-right {
width: 50%;
}
.block-one-right-top img {
height: 100%;
}
.block-one-right-bottom {
padding-top: 25px;
}
<div class="block-one">
<div class="block-one-left">
<img src="https://via.placeholder.com/300x400" alt="">
</div>
<div class="block-one-right">
<div class="block-one-right-top">
<img src="https://via.placeholder.com/300x400?text=Shrink+Me!" alt="">
</div>
<div class="block-one-right-bottom">
<p>Lorem ipsum dolor sit amet, consectetuer diiscing elit, sed diam nonummy nibh dolor it euismod tincidunt ut laoreet dolore.</p>
</div>
</div>
</div>
I am trying to make some elements overlap and staggered using flexbox, but I also need it responsive to stack when on mobile. I am new to flexbox and want to see if I can get some help making this responsive. Below is my html and css. As you can see when you run the snippet, it is not how I want it to look. This is my codepen and that is the desktop layout I would like, then I would like the divs to stack as it gets to mobile: https://codepen.io/ascarb1/full/zWZVRw/
Any help is really appreciated.
body {
max-width: 1600px;
width: 95%;
margin: 0 auto;
}
.home-story-container {
display: flex;
margin: 10em auto;
flex-direction: column;
justify-content: space-between;
align-items: left;
float: none;
}
.home-story-container .home-story-text-block {
height: 373px;
width: 618px;
background: #ddd;
align-self: flex-start;
flex-shrink: 0;
margin-left: 15em;
}
.home-story-container .home-story-text-block .home-story-text-content {
width: 60%;
margin: 4em 0 0 4em;
}
.home-story-container .home-story-image-block {
width: 640px;
align-self: flex-end;
flex-shrink: 0;
margin-right: 14em;
margin-top: -23em;
}
.home-story-container .home-story-video-block {
width: auto;
align-self: flex-start;
flex-shrink: 0;
margin-left: 21em;
margin-top: -10em;
}
.home-story-container .home-story-quote-block {
align-self: flex-end;
flex-shrink: 0;
margin-right: 16em;
margin-top: -9.5em;
width: 413px;
}
<div class="col-md-12">
<div class="home-story-container">
<div class="home-story-text-block">
<div class="home-story-text-content">
<h1>Lorem ipsum dolor sit amet</h1>
<br>
<p>Lorem ipsum dolor sit amet, malesuada quisque sit consectetuer adipiscing odit, sed tortor leo nunc, a vel erat ultricies.</p>
</div>
</div>
<div class="home-story-image-block"><img src="http://via.placeholder.com/640x373"></div>
<div class="home-story-video-block"><iframe width="560" height="315" src="https://www.youtube.com/embed/SkgTxQm9DWM?rel=0" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen=""></iframe></div>
<div class="home-story-quote-block">
<p>Lorem ipsum dolor sit amet, Lorem ipsum dolor sit amet<br><span>Lorem ipsum dolor sit amet.</span></p>
</div>
</div>
</div>
I'm trying to resolve an issue I'm running into. I have a parent div with 3 floating children. I posted a previous question but that only partially resolved my problem. SEE HERE to reference.
So The problem is that the second child div's width is not known. The 1st and 2nd child div have fixed widths.
The 1st and 2nd child have fixed heights.
The 3rd Child div is set to display: block !important; clear: both; width: 100%; so that it goes to the next row and takes up the entire space of the parent div.
The issue is with the 2nd Child element. Since the width is not known and can change dynamically.
What I am trying to achieve is so that the 2nd child div expands horizontally but remains in line with the 1st child div.
In reference to my previous question. Using display: inline-table; does not allow the content to scroll if it overflows.
.container {
background: #ccc;
overflow: hidden;
float: left;
padding:5px;
}
.floating-box {
float: left;
width: 150px;
height: 75px;
margin: 5px;
border: 3px solid #73AD21;
}
.floating-box2 {
float: left;
width: auto;
height: 75px;
margin: 5px;
border: 3px solid #73AD21;
}
.floating-box3 {
float: left;
clear: both;
width: 100%;
height: 75px;
margin: 0;
background: magenta;
}
<div class="container">
<div class="floating-box">Floating box</div>
<div class="floating-box2">Floating box Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minus necessitatibus adipisci quisquam ducimus dolor fugit, officia perferendis harum temporibus laborum iure numquam, assumenda dignissimos neque, quod doloribus nihil autem dolores!</div>
<div class="floating-box3">Floating box</div>
</div>
JSFiddle
You can do it with the Flexbox, if I understand you correctly and this is what you want:
/* reset browser defaults */
* {margin:0;padding:0;box-sizing:border-box}
html, body {width:100%}
.flex-container {
display: flex; /* displays flex-items inline by default */
flex-wrap: wrap; /* enables wrapping */
}
.flex-container > div {border:1px solid}
.one {
flex: 0 0 200px; /* fixed width / adjust to your needs */
}
.two {
flex: 0 1 auto;
max-width: calc(100% - 200px); /* -200px of the .one fixed width */
word-wrap: break-word;
}
.three {
flex: 1 1 calc(100% - 200px); /* -200px of the .one fixed width */
}
.one, .two {height:100px} /* adjust to your needs / can also use just .one or just .two */
<div class="flex-container">
<div class="one">1</div>
<div class="two">2
..........fake content..........
</div>
<div class="three">3</div>
</div>
Thanks, #VXp. I referenced a CodePen and fiddled around with the flexbox. This is very close to the end result I'm trying to achieve.
body {
padding: 2em;
}
.wrapper {
display: flex;
flex-flow: row wrap;
font-weight: bold;
text-align: center;
}
.wrapper > * {
padding: 10px;
flex: 1 100%;
}
.aside-1 {
background: gold;
flex: 1 auto;
height: 155px;
max-width: 155px;
}
.main {
text-align: left;
background: deepskyblue;
flex: 3 0px;
order: 2;
height: 155px;
}
.footer {
background: lightgreen;
order: 3;
}
<div class="wrapper">
<aside class="aside aside-1">Aside 1</aside>
<article class="main">
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
</article>
<footer class="footer">Footer</footer>
</div>
I am struggling with a layout problem and I hope to find some help to solve it.
I am designing a page with row/lane based content.
Each row has multiple div elements with some content.
So it has to be possible to scroll through the rows vertically as well as horizontally.
Now the problem is, that the first div element inside every row is kind of like the row header, which provides some description about the content of that row.
I want this div element to always stay visible during horizontal scrolling.
Position: fixed is not a option since it would prevent the "row-header" to scroll with its content during a vertical scroll.
What it should look like during a horizontal scroll
Here's the fiddle with my code: https://jsfiddle.net/rco56cbp/
html,
body {
font-family: 'Arial', sans-serif;
margin: 0;
}
* {
box-sizing: border-box;
}
header {
background: #F7F7F7;
box-shadow: 0px 2px 6px 0px rgba(0,0,0,0.50);
/**/
width: 100%;
height: 90px;
/**/
display: flex;
align-items: center;
justify-content: center;
position: fixed;
z-index: 55;
top: 0;
}
/* Left Sidebar */
.side-bar-bg {
width: 130px;
height: 100vh;
z-index: -1;
position: fixed;
background: #F7F7F7;
border: 1px solid #E0E0E0;
box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.50);
}
/* Wrapper around main content */
.content-container {
margin-top: 110px;
height:100%;
position:absolute;
width:100%;
}
/* Content elements*/
.lane,
.lane-head,
.phase,
.lane-content {
display: flex;
}
.lane {
margin-bottom: 1.25em;
//flex-direction: row;
align-items: center;
}
.lane-head {
min-width: 130px;
background-color: #ffffff;
box-shadow:0px 0px 0px 1px #BFC0C2 inset;
/* Flex & Layout */
flex-direction: column;
flex-wrap: wrap;
justify-content: center;
align-items: center;
align-self: stretch;
/**/
margin-right: 1em;
}
.lane-label {
font-weight: 500;
font-size: 13px;
color: rgba(82,94,106,0.65);
line-height: 22px;
margin-left: 1em;
margin-right: 1em;
text-align: center;
}
.lane-content {
z-index: -3;
}
/* Grid System */
.col-1 { min-width: 200px; max-width: 200px; }
.col-2 { min-width: 420px; max-width: 420px; }
.col-3 { min-width: 640px; max-width: 640px; }
.col-1, .col-2, .col-3 { margin-right: 20px; }
.textbox {
padding: 0.7em 1em 1.5em 1em;
color: #FFFFFF;
min-width: 200px;
max-width: 200px;
background-color: #78BE20;
}
.phase {
background: #005691;
align-self: stretch;
align-items: center;
padding: 0.6em 1em;
}
/* Typo */
.phase {
font-weight: 500;
font-size: 16px;
color: #FFFFFF;
}
.textbox h3 {
font-weight: bold;
font-size: 16px;
margin: 0 0 0.3em 0;
}
.textbox p {
font-weight: normal;
font-size: 13px;
margin: 0 0;
}
<header>
<h1>Header</h1>
</header>
<div class="side-bar-bg"></div>
<!------ CONTENT ------>
<div class="content-container">
<div class="lane">
<div class="lane-head"><span class="lane-label">Small Boxes</span></div>
<div class="lane-content">
<div class="phase col-2">Lorem Ipsum</div>
<div class="phase col-3">Bacon Ipsum</div>
<div class="phase col-2">Egg Ipsum</div>
</div>
</div>
<div class="lane">
<div class="lane-head"><span class="lane-label">Bigger Boxes</span></div>
<div class="lane-content">
<div class="textbox col-1">
<h3>Aenean commodo</h3>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</p>
</div>
<div class="textbox col-1">
<h3>Consequat</h3>
<p>Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus.</p>
</div>
<div class="textbox col-1">
<h3>Consequat</h3>
<p>Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus.</p>
</div>
<div class="textbox col-1">
<h3>Consequat</h3>
<p>Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus.</p>
</div>
<div class="textbox col-1">
<h3>Consequat</h3>
<p>Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus.</p>
</div>
<div class="textbox col-1">
<h3>Consequat</h3>
<p>Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus.</p>
</div>
<div class="textbox col-1">
<h3>Consequat</h3>
<p>Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus.</p>
</div>
</div>
</div>
</div>
The fixed left sidebar shall serve as a background to the "lane-headers".
The reason I want the lane-headers and the lane-content to be inside one div container is that later the whole canvas becomes dynamic and interactive. The content will be generated dynamically and the user will be able to interact with the canvas with drag-drop and so on.
I would appreciate your help very much, thanks in advance!
Hi you need to use javascript as well, once you scroll down or up add a class say posi_stat which will be position:static.and when you do horizontal scrolling just remove the class. In default case it will be position :fixed .
Something like this , you need to remove the class , and add on scrolldown too
$(function() {
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 500) {
//your code , what should be done//
}
});
});
Similarly to it for .scrollBottom(); .scrollRight(); .scrollLeft();
Okay I kind of found a solution to it thanks to this: Fixed position in only one direction in future releases of CSS?
Although the javascript solution did not work for me (I still can't figure out why), the CSS solution works pretty good.
By adding the following lines to the .lane-head class the problem was solved:
left: 0;
position: -webkit-sticky;
position: -moz-sticky;
position: -o-sticky;
position: -ms-sticky;
position: sticky;
Using the new "position: sticky" property you can perfectly stick any element basically anywhere you want.
Unfortunately Chrome still does not support this yet, but Safari and Firefox do.