Scaling and aligning a simplistic website with image content - css

I am working on a simplistic website to show pictures in a single stream. To keep javascript to a minimum (just lazy loading), I only use a single relatively high-resolution version of each image and then rely on CSS to resize.
My question is how the rest of the website, at least the logo and the menu, can be best resized relative to the size of the images. After reading the CSS grid guide I decided to use a grid with grid-auto-flow: row.
The problem: I want the logo to flush left with the left of the top image and the menu to flush right with the right of the top image (all horizontal images have the same width).
My current code either aligns logo and menu to the corners of the page (as with the code below) or centers both (if I move the header into the grid as first item)
#main{
height: max-content;
display: grid;
grid-auto-flow: row;
grid-row-gap: 8em;
place-items: center center;
}
.photo_horizontal, .photo_vertical{
object-fit: contain;
height: auto;
}
.photo_horizontal{
width: 80vw;
max-height: 80vh;
}
.photo_vertical{
width: 60vw;
max-height: 90vh;
}
/* THE HEADER */
header{
display: grid;
grid-auto-flow: column;
}
#logo{
width: 15em;
justify-self: start;
}
header > div{
margin: auto 0 0 auto;
}
<header>
<img id="logo" src="https://via.placeholder.com/500x100/ff7f7f/333333?text=some%20website"/>
<div>
menu1
menu2
</div>
</header>
<div id="main">
<img class="photo_horizontal" src="https://picsum.photos/3000/2000"/>
<img class="photo_vertical" src="https://picsum.photos/2000/3000" />
<img class="photo_vertical" src="https://picsum.photos/2000/3000" />
<img class="photo_horizontal" src="https://picsum.photos/3000/2000" />
</div>
Is there an elegant way to resize images relative to the viewport but still align other content accordingly? I tried to pad logo and menu left/right but the necessary padding depends on the actual size of the image.
A pen can be found here.
To clarify, this is how it currently is and this is what I want.

The main problem is setting .photo_horizontal's .max-height: 80vh; causes it to not always honor the width: 80vw; which means the width of the .photo_horizontal is not easily calculated. That makes it difficult to make the <header> the same width.
You can do this:
header {
width: 80vw;
margin: auto;
}
But it only works if you also get rid of the max-height: 80vh rule for .photo_horizontal.
https://codepen.io/km0ser/pen/LYpqeYB

Why not include the header within #main
/* Nothing wrong with CSS grid, just Flexbox is simpler */
#main {
display: flex;
flex-direction: column;
align-items: center;
border: 1px solid;
}
/* height being auto will keep the aspect ratio */
/* horizontal photo take full width */
.photo_horizontal {
max-width: 100%;
}
/* horizontal photo take some portion of width */
.photo_vertical {
max-width: 80%;
}
header {
display: flex;
width: 100%;
}
#logo {
width: 15em;
}
header>div {
margin: auto 0 0 auto;
}
<div id="main">
<header>
<img id="logo" src="https://via.placeholder.com/500x100/ff7f7f/333333?text=some%20website" />
<div>
menu1
menu2
</div>
</header>
<img class="photo_horizontal" src="https://picsum.photos/3000/2000" />
<img class="photo_vertical" src="https://picsum.photos/2000/3000" />
<img class="photo_vertical" src="https://picsum.photos/2000/3000" />
<img class="photo_horizontal" src="https://picsum.photos/3000/2000" />
</div>

Thanks to the answers here I figured out a solution. There are three components:
As #Zohir Salak pointed out, much simpler CSS can be obtained using flexbox.
The header can be part of main even though this is not essential to the solution.
As #kmoser pointed out, the max-height constraint on images makes it hard to set a proper max-width constraint for the header, a problem that isn't solved by 1. and 2. yet. However, since all of my pictures are 3:2 ratio, a max-height constrained can be turned into a max-width constrained easily and then combined with a min via max-width: min(80vw, 3 / 2 * 80vh);.
/* Nothing wrong with CSS grid, just Flexbox is simpler */
#main {
display: flex;
flex-direction: column;
align-items: center;
border: 1px solid;
}
/* height being auto will keep the aspect ratio */
/* horizontal photo take full width */
.photo_horizontal {
max-width: min(80vw, 3 / 2 * 80vh);
}
/* horizontal photo take some portion of width */
.photo_vertical {
max-width: min(80vw, 2 / 3 * 80vh);
}
header {
display: flex;
width: 100vw;
max-width: min(80vw, 3 / 2 * 80vh);
}
#logo {
width: 15em;
}
header>div {
margin: auto 0 0 auto;
}
<div id="main">
<header>
<img id="logo" src="https://via.placeholder.com/500x100/ff7f7f/333333?text=some%20website"/>
<div>
menu1
menu2
</div>
</header>
<img class="photo_horizontal" src="https://picsum.photos/3000/2000"/>
<img class="photo_vertical" src="https://picsum.photos/2000/3000" />
<img class="photo_vertical" src="https://picsum.photos/2000/3000" />
<img class="photo_horizontal" src="https://picsum.photos/3000/2000" />
</div>
Alternatively, see the same code in a pen here.

Related

How to fix flexbox overlapping divs when using media query?

I'm asking my first question here, so I apologize in advance if I didn't explain something well.
I'm currently developing portfolio website (Angular 13 with Sass). I've come to a point where I have two divs placed next to each other inside of a flexbox. I use media query (mobile view) to achieve divs to place below each other. One div contains text and other image.
I'm using Sass for flex box
#mixin flex-container($flexdirection, $justifycontent: false) {
#if $justifycontent {
justify-content: $justifycontent;
} #else {
justify-content: center;
}
display: flex;
flex-wrap: wrap;
row-gap: 20px;
align-items: center;
flex-direction: $flexdirection;
}
HTML component looks like this
<div class="about" id="about" #about>
<div class="about__details">
<h1 class="about__title">{{title}}<span class="purple_highlight">A</span>ndjela. <span class="wave">👋</span>
</h1>
<p class="about__paragraph">{{paragraph}}
</p>
<a href="https://drive.google.com/file/d/1PK82zuN4g_Ly5nmNIgRpIsEW9j_gnyaS/view?usp=share_link" target="_blank">
<button class="about__cv_button">My resume</button>
</a>
</div>
<div class="about__img">
<img src="assets/img/profilePicture.png" alt="profile">
</div>
</div>
CSS looks like this
#include mq-between(xs, sm) {
.about {
#include flex-container(row);
height: 100vh;
&__img {
background-color: aqua;
bottom: 0;
right: 0;
flex-shrink: 0;
}
img {
max-width: 100%;
max-height: 100%;
}
&__details {
background-color: blanchedalmond;
left: 10%;
right: 10%;
}
}
}
Result looks like in picture
I've tried using flex-direction as column, flex-basis, max-width, max-height, padding and margin, but nothing seems to make changes for what I'm looking for.
What am I missing to show the divs beneath each other with the correct height?

Two-Column Newspaper Layout with CSS Grid

I've got CSS grid to produce a two-column layout. But the problem is that it's not top-aligning content in each column.
For example, in the second column, the last element should top-align to but up against the other column-two element.
body>div {
display: grid;
grid-template-columns: 50% 50%;
grid-template-rows: auto auto;
grid-auto-flow: column;
/* https://codepen.io/maddesigns/pen/oZGWRN */
/* https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow */
}
body>div>div:nth-of-type(1) {
height: 300px;
}
body>div>div:nth-of-type(2) {
height: 100px;
}
body>div>div:nth-of-type(3) {
height: 200px;
}
<div style="">
<div style="background:red">
1
</div>
<div style="background:green;">
2
</div>
<div style="background:yellow">
3
</div>
<div style="background:pink">
4
</div>
</div>
I couldn't use flex for this layout because I wanted to achieve this layout without defining the container height. column-count:2 would have worked without defining the container height but then I couldn't use div reordering.
So I'm using CSS grid because div reordering is still available (e.g./i.e. order:–1; works well) and it auto-divies up what to put in each of the two columns.
The gird is acting exactly as intended, to keep order and symmetry just like this. I can recommend using 2 grids side by side to achieve what you're looking for. Here's an example that I made to demonstrate this:
.left{
display: grid;
grid-template-rows: auto auto;
grid-auto-flow: column;
width: 50%;
float: left;
/* https://codepen.io/maddesigns/pen/oZGWRN */
/* https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow */
}
.right{
display: grid;
grid-template-rows: auto auto;
grid-auto-flow: column;
width: 50%;
/* https://codepen.io/maddesigns/pen/oZGWRN */
/* https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow */
}
.left>div:nth-of-type(1) {
height: 300px;
}
.left>div:nth-of-type(2) {
height: 100px;
}
.right>div:nth-of-type(1) {
height: 200px;
}
.right>div:nth-of-type(2) {
height: 50px;
}
<div class="left" style="">
<div style="background:red">
1
</div>
<div style="background:green;">
2
</div>
</div>
<div class="right">
<div style="background:yellow">
3
</div>
<div style="background:pink">
4
</div>
</div>
In fact, until a CSS technology arrives with the ability to automatically close the gaps, CSS in general has no solution. Something like this would probably require reflowing the document, so I'm not sure how useful or efficient it would be.
Source: https://stackoverflow.com/a/45200955/1625909

Why is height:auto not working for this image?

I have a flexbox container with two flex items in it. One is an image and the other a paragraph. I've been trying to resize the image proportionally by giving width:some-percentage and height:auto but it's not working. Please help me solve this.
.item{
display:flex;
}
img{
width: 25%; /* not working */
height: auto;
}
<div class="item">
<img
src=
"https://png.pngtree.com/element_origin_min_pic/16/10/16/105802ebe43fe0f.jpg"/>
<p>some paragraph</p>
</div>
JSFiddle link - https://jsfiddle.net/dizzyramen/xfot3Lwv/2/
A default setting on a flex container is align-items: flex-start.
In a row-direction container, this makes flex items, not having a defined height (e.g. height: auto), extend the full height of the container (full explanation).
In this particular case, however, the image is stretching to its fullest, and expanding the size of the container along with it.
The solution is to set a height limit on the container or override the default with align-items: flex-start on the container or align-self: flex-start on the item.
jsFiddle demo
.item {
display: flex;
}
img {
width: 25%;
align-self: start; /* new */
}
<div class="item">
<img src="https://png.pngtree.com/element_origin_min_pic/16/10/16/105802ebe43fe0f.jpg" />
<p>some paragraph</p>
</div>
here is another option:
wrap your img in a div <div class="image-wrapper"> and set manage the width in this node.
asign width: 100%; height: auto; to the img so it adjust proportionally to its parent.
Here you have it in a snippet. Hope it helps.
<div class="item">
<div class="image-wrapper">
<img
src=
"https://png.pngtree.com/element_origin_min_pic/16/10/16/105802ebe43fe0f.jpg"/>
</div>
<p>some paragraph</p>
</div>
<style>
.item{
display:flex;
}
.image-wrapper {
width: 25%; /* means 25% of .item */
}
img{
width: 100%; /* means 100% of its parent .image-wrapper */
height: auto;
}
</style>
It happens because, per default the tag <img>is inline. You need to change it to block or flex

Align scroll down arrow to the bottom center of a full-screen div in WPBakery Visual Composer

I have a series of full-screen divs in Visual Composer and I want an arrow at the bottom of each one indicating to users they should scroll for more content. I tried absolute positioning on the divs containing the icon with no luck. All I've done is move the icon a few pixels to th
<section class="l-section wpb_row height_full valign_center width_full with_img" id="home">
<div class="l-section-img loaded" data-img-width="1920" data-img-height="809">
</div>
<div class="l-section-h i-cf">
<div class="g-cols vc_row type_default valign_top">
<div class="vc_col-sm-12 wpb_column vc_column_container">
<div class="vc_column-inner">
<div class="wpb_wrapper">
<div class="w-image align_center" id="mainlogo">
<div class="w-image-h"><img src="logo.png" class="attachment-full size-full">
</div>
</div>
<div class="ult-just-icon-wrapper">
<div class="align-icon" style="text-align:center;">
<a class="aio-tooltip" href="#whatis">
<div class="aio-icon none " style="display:inline-block;">
<i class="Defaults-chevron-down"></i>
</div>
</a>
</div></div></div></div></div></div></div>
</section>
Existing CSS:
.aio-icon.none {
display: inline-block;
}
.aio-tooltip {
display: inline-block;
width: auto;
max-width: 100%;
}
.vc_column-inner {
display: flex;
flex-direction: column;
flex-grow: 1;
flex-shrink: 0;
}
.wpb_column {
position: relative;
}
.vc_column_container {
display: flex;
flex-direction: column;
}
.vc_row {
position: relative;
}
.l-section-h {
position: relative;
margin: 0 auto;
width: 100%;
}
The icon itself is the Defaults-chevron-down.
Do you have an idea how to position that icon properly?
I also struggled a little with this. But there is a rather quick and dirty fix for this:
Just put another row below the full height row. Place your icon there and give this element a top margin of i.e. -200px.
For some strange reason the rather logical approach to put the icon in the full height row itself and to position it absolute to the bottom is not properly supported by the source generated from WPB.
I had this issue this week. The way I resolved it was added the icon in that row/section (in my case a single image element with a custom link to a .svg) and added a class to it.
The CSS for the class was then:
position:absolute;
margin-left: auto;
margin-right: auto;
left: 0;
right: 0;
text-align: center;
margin-top:-30px;
(I added a negative margin top as I noticed the icon was cutting of a little on my Google Pixel phone with the fixed bottom bar so that pulled it up a little.)

How can I display two divs inline while also centering them vertically using flex-box?

I have 2 divs inside another div container. I'm using flexbox to center them vertically inside the container, but I want them to be next to each other horizontally rather than one on top of the other. I tried a few different approaches including changing the display property of the container from flex to inline-flex as well as adding display:inline-block to the child divs. Here is a picture of what I'm working with. As you can see the 2 divs (the picture and group 1 label) are centered within the parent div, but I want Group 1 to be next to the picture instead of below it.
Code below and link to JSfiddle:
HTML
<div class="user-group">
<div>
Picture 1
</div>
<div class="user-group-name"><h4>Group 1</h4></div>
</div>
JS
.user-group{
font-family: 'Purista';
border: solid 1px;
display: inline-flex;
float: left;
justify-content:center;
align-content:center;
flex-direction:column; /* column | row */
width: 50%;
height: 200px;
}
.user-group > div{
display: inline-flex;
}
It depends if you intend to have multiple picture + text pairs in the element. If you don't, simply using align-items: center should fix your issue. There are some issues with your code:
align-content is not a flex property
Avoid using display: inline-flex, your situation does not call for it
Floats and flex are conflicting layout methods. Pick one—in this case, we settle for flex.
Use the default flex direction, which is row (if undeclared, it defaults to row, so we can just remove that property)
.user-group {
font-family: 'Purista';
border: 1px solid;
display: flex;
justify-content: center;
align-items: center;
width: 50%;
height: 200px;
}
h4 {
margin: 0;
}
<div class="user-group">
<div>
<img src="https://placehold.it/32x32" alt="" title="" />
</div>
<div class="user-group-name">
<h4>Group 1</h4></div>
</div>
On the other hand, if you have multiple picture + text pairs, you will have to resort to nesting. Each pair will have to be wrapped by an additional <div>:
.user-group {
font-family: 'Purista';
border: 1px solid;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
width: 50%;
height: 200px;
}
.user-group > div {
display: flex;
margin-bottom: 10px;
}
h4 {
margin: 0;
}
<div class="user-group">
<div>
<img src="https://placehold.it/32x32" alt="" title="" />
<div class="user-group-name"><h4>Group 1</h4></div>
</div>
<div>
<img src="https://placehold.it/32x32" alt="" title="" />
<div class="user-group-name"><h4>Group 2</h4></div>
</div>
<div>
<img src="https://placehold.it/32x32" alt="" title="" />
<div class="user-group-name"><h4>Group 3</h4></div>
</div>
</div>

Resources