Backstory: The following flexbox based layout works as expected. As I shrink the width of the browser all three images scale down at equal rates. If you run the code snippet please click the Full page link and scale the browser to see this simple effect.
.flexParent {
display: flex;
margin: 0 auto;
width: 80%;
}
.flexChildOne {
margin-right: 16px;
}
.flexChildOne img {
width: 100%;
height: auto;
}
.flexInterior {
display: flex;
overflow: hidden;
}
.flexChildTwo {
width: 400px;
margin-right: 16px;
}
.flexChildTwo img {
width: 100%;
height: auto;
}
.flexChildThree {
width: 400px;
}
.flexChildThree img {
width: 100%;
height: auto;
}
<div class="flexParent">
<div class="flexChildOne"><img src="https://i.stack.imgur.com/9lzSH.jpg"></div>
<div class="flexInterior">
<div class="flexChildTwo"><img src="https://i.stack.imgur.com/8Q4Q7.jpg"></div>
<div class="flexChildThree"><img src="https://i.stack.imgur.com/5vBC6.jpg"></div>
</div>
</div>
However when I add flex-direction: column; to the flexInterior class the effect doesn't work as needed. The left image scales as before but the two images inside flexInterior remain static. Their right edges get progressively cut off as the browser shrinks instead of scaling. This is because of the line overflow: hidden; which is needed in the original row layout to cause the scaling effect but creates this new cutting problem in the column layout version.
Question: In the column layout how do I make the images scale similar to the row layout? This is a simplified example. In the actual version I'm using media queries to display either the column or row version depending on the width of the browser.
.flexParent {
display: flex;
margin: 0 auto;
width: 80%;
}
.flexChildOne {
margin-right: 16px;
}
.flexChildOne img {
width: 100%;
height: auto;
}
.flexInterior {
display: flex;
flex-direction: column; /* Only line that was changed */
overflow: hidden;
}
.flexChildTwo {
width: 400px;
margin-right: 16px;
}
.flexChildTwo img {
width: 100%;
height: auto;
}
.flexChildThree {
width: 400px;
}
.flexChildThree img {
width: 100%;
height: auto;
}
<div class="flexParent">
<div class="flexChildOne"><img src="https://i.stack.imgur.com/9lzSH.jpg"></div>
<div class="flexInterior">
<div class="flexChildTwo"><img src="https://i.stack.imgur.com/8Q4Q7.jpg"></div>
<div class="flexChildThree"><img src="https://i.stack.imgur.com/5vBC6.jpg"></div>
</div>
</div>
The child elements of .flexInterior are wider than their parent
Remove the width from .flexChildTwo and .flexChildThree and add it to .flexInterior
.flexInterior {
display: flex;
flex-direction: column;
overflow: hidden;
width: 400px
}
Example: https://codepen.io/IanJohnson/pen/QzqggE?editors=1100
You will also want to get rid of the margin-right when its in the column layout
Related
I want to put three images next together by using flexbox and responsive units in this case percentage(%). I have 2 issues: (1) justify-content does not work because I use % for flex items. (2) The tall of my images are getting bigger than the wide, in other word width and height of my images are not relative together because I used auto keyword for the height of images so I can have width and height relative. I would be very grateful if you could help me. I will include my code below.
.services h2 {
margin: 3.125rem 0 2rem;
}
#services-container {
display: flex;
width: 100%;
}
.service-item {
width: 90%;
height: 65%;
overflow: hidden;
}
.service-item img {
width: 100%;
height: auto;
display: block;
}
<section class="services">
<h2>our services</h2>
<div id="services-container">
<div class="service-item hotel">
<img src="./resources/pictures/hotel.jpg" alt="hotel">
<h4>The best hotels</h4>
</div>
<div class="service-item air-plane">
<img src="./resources/pictures/airplane.jpg" alt="airplane">
<h4>The best airline services</h4>
</div>
<div class="service-item food">
<img src="./resources/pictures/food.jpg" alt="food">
<h4>The highest quality foods</h4>
</div>
</div>
</section>
First, you can set the height to 100% and width to auto and use justify-content on parent like so :
.services h2 {
margin: 3.125rem 0 2rem;
}
#services-container {
display: flex;
width: 100%;
justify-content: space-between;
}
.service-item {
width: 30%;
height: 100%;
overflow: hidden;
}
.service-item img {
width: auto;
height: 100%;
display: block;
}
Hope it helps
The code that appears below creates the following layout:
The important part is that the content, although centered on the screen when not overflowing, never overlaps the navbar and has its own scrollbar:
The problem is that this layout is achieved with the help of padding (marked by a comment in the code below), which results in the additional scrollbar on the right of the screen.
How can I design the same layout that would have only one scrollbar - the one in the content?
Please note that the solution should not break the following details:
The rounded corners and the shadow.
The title in the content block not participating in scrolling.
The image covering the whole scrollable content, so it scrolls together with the content.
In addition, it would be great if this can be achieved without as many nested div's as I have right now.
Edit: I am ready to go with the suggestion of #JHeth in the comments section. However, I would still be interested if someone can come up with an alternative design that does not rely on padding for centering.
Here is the code (CodePen):
* {
padding: 0;
margin: 0;
}
html {
font-size: 62.5%;
}
:root {
--navbar-height: 3rem;
}
.navbar {
width: 100%;
text-align: center;
font-size: 2rem;
line-height: var(--navbar-height);
background-color: lightgreen;
}
.centering {
position: absolute;
inset: var(--navbar-height) 0 0 0;
display: flex;
flex-direction: column;
align-items: center;
& .auto-margin {
margin: auto;
// For scrollable content
display: flex;
max-height: 100%;
padding-bottom: calc(var(--navbar-height)); // Causes scrolling
}
}
.content-block {
display: flex;
flex-direction: column;
.title {
font-size: 2rem;
position: sticky;
}
.content-outer-container {
display: flex;
flex-direction: column;
overflow-y: auto;
border-radius: 1em;
box-shadow: 0 1em 2em rgba(black, 0.4);
.content-container {
width: 300px;
overflow-y: auto;
.content {
position: relative;
padding: 1em;
&:before {
content: "";
z-index: -1;
position: absolute;
top: 0;
left: 0;
right: 0;
height: 100%;
background-position: center;
background-image:
url(http://www.freegreatpicture.com/files/147/18380-hd-color-background-wallpaper.jpg);
}
}
}
}
}
<div class="navbar">An Amazing Navbar</div>
<div class="centering">
<div class="auto-margin">
<div class="content-block">
<div class="title">My Title</div>
<div class="content-outer-container">
<div class="content-container">
<div class="content">
<h1>Line1</h1>
<h1>Line2</h1>
<h1>Line3</h1>
<h1>Line4</h1>
<h1>Line5</h1>
</div>
</div>
</div>
</div>
</div>
</div>
simply remove max-height:100%; to .centering .auto-margin and it'll works!
.centering .auto-margin {
margin: auto;
display: flex;
/* max-height: 100%; */
padding-bottom: calc(var(--navbar-height));
}
Sorry, another flexbox related question :)
I have two flex elements :
A container (red) containing a centered div (yellow)
A footer (blue) with an undefined height
The red container has a flex-grow:1 attribute, forcing it to take the remaining space on the screen
The issue happens when the yellow element is bigger than the screen size. I would like my red container to grow based on its content. Any idea of how I could do that ?
HTML:
<div class="container">
<div class="content"></div>
</div>
<div class="footer"></div>
CSS:
body,
html {
margin: 0;
height: 100%;
display: flex;
flex-direction: column;
}
.container {
flex-grow: 1;
display: flex;
align-items: center;
justify-content: center;
background: red;
}
.content {
background: yellow;
height: 2000px;
width: 100px;
}
.footer {
flex-shrink: 0;
height: 50px;
background-color: blue;
}
https://codepen.io/stepinsight/pen/roRVGQ
== EDIT ==
Andre helped me find the answer, thanks heaps !
The only thing you need to change in the code above is to replace height by min-height and the % by vh for the body/html tags 🎉
body,
html {
margin: 0;
min-height: 100vh;
display: flex;
flex-direction: column;
}
Simply remove the height property on the body element and add height: 100% to html
* { box-sizing: border-box; }
html {
height: 100%
}
body {
display: flex;
flex-direction: column;
margin: 0;
padding: 0;
}
.container {
display: flex;
align-items: center;
justify-content: center;
background: red;
}
.content {
background: yellow;
height: 2000px;
width: 100px;
}
.footer {
height: 50px;
background-color: blue;
}
Corrected: https://codepen.io/ferreirandre/pen/maoVvb
Feel free to play around with the height of .content
Trying to make an empty state placed below an app-header. I want it to take the full width and full height (minus the height of the app-header) of the entire screen.
So far, I have this, but it doesn't seem to work:
<app-header-layout>
<app-header>
.....
</app-header>
<div id="empty-state" style="width: 100%; height: 100%; background: #F00; white-space: nowrap;">
.....
</div>
</app-header-layout>
Still no go. The empty state has the full width that I want, but not the height that I want.
Please help me out.
There's a couple way to do this. You can use a flex-box (explained here):
body,
html {
height: 100%;
}
body {
margin: 0px;
display: flex;
flex-direction: column;
}
app-header {
min-height: 50px;
}
#empty-state {
overflow: auto;
background: #F00;
flex-grow: 1;
overflow: auto;
}
<body>
<app-header>...</app-header>
<div id="empty-state">
.....
</div>
</body>
You can also simply absolutely position your elements. Simply account for the height of app-header and offset #empty-state by this height. Like this:
body,
html {
height: 100%;
}
body {
margin: 0;
}
app-header {
width: 100%;
height: 50px;
}
#empty-state {
position: absolute;
top: 50px;
bottom: 0;
background: #F00;
width: 100%;
}
<app-header-layout>
<app-header>
.....
</app-header>
<div id="empty-state">
.....
</div>
</app-header-layout>
First container fine, u can see 2 images and there are 6 images with overflow. (vertical)
Container2 problem, I want to make horizontal images list with overflow (Only x / horizontal).
My css so far:
#container {
display: block;
width: 80%;
height: 40vw;
background: red;
margin-bottom: 50px;
}
#imglist {
display: block;
overflow: auto;
height: 40vw;
width: 40%;
}
#imglist div {
display: block;
width: 100%;
}
#imglist div img {
width: 100%;
}
/*Problem*/
#container2 {
display: block;
width: 80%;
height: 20vw;
background: red;
}
#imglist2 {
overflow-x: scroll;
display: block;
width: 100%;
height: 15vw;
}
#imglist2 div {
width: 20%;
display: inline;
}
Example in JSFiddle: https://jsfiddle.net/n4a2tc7s/
Explicitly control wrapping and hiding
In addition to defining white-space: nowrap on the container, you should explicitly define overflow-y: hidden instead of overflow-x: scroll. Scroll bars will automatically appear on overflowed containers (unless you already have a rule preventing them), so you need only to restrict the scroll bars on the y axis for your scenario.
In the following example, I also set height: 100% on #imglist2 because the 15vw declaration was causing the scrollbar to crop the images. If that was intentional, feel free to roll it back in:
#container2 {
display: block;
width: 80%;
height: 20vw;
background: red;
white-space: nowrap;
}
#imglist2 {
overflow-y: hidden;
display: block;
width: 100%;
/*height: 15vw;*/
height: 100%;
}
#imglist2 div {
width: 20%;
display: inline;
}
<section id="container2">
<div id="imglist2">
<div>
<img src="http://img.youtube.com/vi/Je7VuV9yHIw/1.jpg">
</div>
<div>
<img src="http://img.youtube.com/vi/uxps_fYUeJk/1.jpg">
</div>
<div>
<img src="http://img.youtube.com/vi/Zvr3cwbbqHU/1.jpg">
</div>
<div>
<img src="http://img.youtube.com/vi/Ka9xtXPD3BA/1.jpg">
</div>
<div>
<img src="http://img.youtube.com/vi/U8HVQXkeU8U/1.jpg">
</div>
<div>
<img src="http://img.youtube.com/vi/e7_UUfokexM/1.jpg">
</div>
</div>
</section>
Try to add this :
#container2 {
display: block;
width: 80%;
height: 20vw;
background: red;
white-space: nowrap;
}