Adaptive mosaic of videos and pictures using flex - css

Using flex, I would like to display an adaptive mosaic of Videos and Pictures, so each time I will add a new video or picture, the Tile will auto adjust.
Here is an exemple of what I m looking for:
[NOTE]: all the Tiles are the same width and height :)
Here is the HTML code:
[NOTE]: I didnt find how to make work flex on StackOverflow.
.flex-container {
display: flex;
background-color: Green;
flex-wrap: wrap;
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0;
z-index: 10;
}
.flex-container > div {
background-color: pink;
height:100%;
}
.flex-container > div > div.image {
background-image: url("https://www.gettyimages.ca/gi-resources/images/EnterpriseSolutions/StandOut_Creative.jpg");
background-position: center right;
background-size: cover;
width:100%;
height:100%;
}
<div class="flex-container">
<div style="width:50%">
<div class="image"></div>
</div>
<div style="width:50%">
<div class="image"></div>
</div>
<div style="width:50%">
<div class="video">
<video src="http://link.to.video.mp4" autoplay loop muted></video>
</div>
</div>
<div style="width:50%">
<div class="image"></div>
</div>
</div>
So In the wrap flex-container, I have "image" div where the Image is in Background. And "video" div.
I found the way the auto adjust the image, but I dont how to do the same for the video.
Did you find a way to auto adjust video in wrap container?
Thanks.

Your flexbox code is okay (by default, the flex direction is by row, and it wraps on multiple lines to give the mosaic effect). The main problem is the position property in the main container. I removed the fixed position property, along with the associated containers.
/* Main Container */
.flex-container {
display: flex;
/* flex-direction: row; <-- Value by default */
flex-wrap: wrap;
width: 100%;
z-index: 10;
background-color: green;
}
I´ve also removed the height on both the main container and the direct children. As for the heights of the <div> with the .image class, i replaced the percentage value with a vh value. Let's define the element in the mosaic taking the full height of the viewport with the value 100vh.
/* Image Container */
.flex-container > div > div.image {
background-image: url("https://www.gettyimages.ca/gi-resources/images/EnterpriseSolutions/StandOut_Creative.jpg");
background-position: center right;
background-size: cover;
width:100%;
height:100vh; /* <-- Height is full height of the viewport */
}
Let´s tackle the video issue. Maintaining the conditions in the HTML code, I've defined CSS for both the video container and the video element, Both will take the same width and height as the <div> elements with the .image class (100% width, 100vh height).
To adjust the video to take the entire size of the container, in it I used the object-fit property, with the value fill.
/* Video Container */
.flex-container > div > div.video {
width: 100%;
height: 100vh;
}
/* Video Element */
.flex-container > div > div.video video {
width: 100%;
height: 100vh;
object-fit: fill; /* <-- The video fills the entire video container */
}
Code Snippet
The mosaic is in action in the snippet below. Note that:
I added margin zero and padding zero to the entire page for aesthetic reasons.
The video elements feature a sample MP4 video.
Your original code has four mosaic elements, the snippet below has six. Along with the four original elements, there are two more. You can play with it and see the mosaic adjusts itself with the present elements.
* {
margin: 0;
padding:0;
box-sizing: border-box;
}
.flex-container {
display: flex;
flex-wrap: wrap;
width: 100%;
z-index: 10;
background-color: green;
}
.flex-container > div {
background-color: pink;
}
.flex-container > div > div.image {
background-image: url("https://www.gettyimages.ca/gi-resources/images/EnterpriseSolutions/StandOut_Creative.jpg");
background-position: center right;
background-size: cover;
width:100%;
height:100vh;
}
.flex-container > div > div.video {
width: 100%;
height: 100vh;
}
.flex-container > div > div.video video {
width: 100%;
height: 100vh;
object-fit: fill;
}
<div class="flex-container">
<div style="width:50%">
<div class="image"></div>
</div>
<div style="width:50%">
<div class="image"></div>
</div>
<div style="width:50%">
<div class="video">
<video src="http://techslides.com/demos/sample-videos/small.mp4" autoplay loop muted></video>
</div>
</div>
<div style="width:50%">
<div class="image"></div>
</div>
<div style="width:50%">
<div class="image"></div>
</div>
<div style="width:50%">
<div class="video">
<video src="http://techslides.com/demos/sample-videos/small.mp4" autoplay loop muted></video>
</div>
</div>
</div>

Related

How to have fixed div height irrespective of image height within it

I have a row with three coloumns. I want to have a image on each coloumn's divs with same height irrespective of image size in each div.
I want the images to get resized with in a div. But i get different size of divs as the image size of myImage1.png, myImage2.png and myImage3.png is different.
This is happening because i have fixed padding in my 'bg' class. Can somebody help me to fix this? Below is my HTML and CSS code.
<div class="row IDE_container">
<div class="col-lg-3 col-md-3 col-sm-3">
<div class="bg">
<img src="myImage1.png" class="IDE_div" />
</div>
</div>
<div class="col-lg-2 col-md-2 col-sm-2">
<div class="circle_bg circle_bg_sm">
<img src="myImage2.png" class="IDE_div" />
</div>
</div>
<div class="col-lg-3 col-md-3 col-sm-3">
<div class="circle_bg">
<img src="myImage3.png" class="IDE_div" />
</div>
</div>
</div>
.bg{
background-color: #ededed;
border-radius: 100%;
text-align: center;
padding: 35% 5%;
width: max-content;
max-width: 100%;
box-shadow: 0 0 3px 1px #DDD;
}
.IDE_div {
display: inline-block;
position: relative;
width: 100%;
height: 100%;
}
.IDE_container {
display: flex;
align-items: baseline;
}
For various kind of images, so can use object-fit property.
Add the CSS like this:
.IDE_div{
width: 100%;
object-fit: cover;
height: 300px; /* only if you want fixed height */
}
<div class="col-3">
<div class="circle_bg">
<img src="myImage3.png" class="IDE_div" />
</div>
</div>
You will find the details about object-fit and object-position here : https://css-tricks.com/on-object-fit-and-object-position/
You need to set a height or max-height on the divs containing the images, or they will adapt to the height of their content (the images). As you've set the images to take up 100% width and height, and haven't constrained their parents, they will get as large as they can based on the original image size.
So, for example :
.IDE_container {
display: flex;
align-items: baseline;
div.col-3 {
div {
height: 200px;
.IDE_div {
display: inline-block;
position: relative;
width: 100%;
height: 100%;
&::before {
content: "";
position: absolute;
top: 50%;
left: 50%;
width: var(--val);
padding-bottom: var(--val);
transform: translate(-50%, -50%);
z-index: -1;
border-radius: 50%;
}
}
}
}
}
You could give all containers the same class (e.g. fixed-height-bg) to style them more easily.
Also note: You don't need to give your columns individual classes for different screen sizes, as they always take up the same proportion. So, you can just use
<div class="col-3">
<div class="circle_bg">
<img src="myImage3.png" class="IDE_div" />
</div>
</div>
EDITED to add: if you want the images to maintain their proportions, you need to change your css to look like this:
img {
height: 100%; /* height of the parent container if specified, or of the image itself */
width: auto; /* will maintain the proportions of the image */
}
You can also switch those values, to height: auto; width: 100%; if you want the images to take the full width.

Two rows div layout. Building flexible layout that should adapt to different screen sizes

I'm trying to build a flexible layout that should adapt to different screen sizes as the following pictures show.
It's basically two div rows, occupying each 50% of the vertical size of the screen.
Top div is a container to hold pictures and bottom div will display a leaflet map.
I'd like the Image div to keep aspect ratio so image is not deformed, ans Map div to adapt horizontally.
So far, my code is basic and looks like this :
<div id="container">
<div id="Top div">
<div id='image'>Image</div>
</div>
<div id="Bottom div">
<div id='map'>Map</div>
</div>
</div>
Any idea of the CSS style I should add to each div to achieve this layout ?
Image layout desktop
Image layout smartphone
You could use Flexbox to achieve this layout. Refer to my CSS below and check out the attached Codepen.
#container {
display: flex;
flex-flow: row wrap;
}
#Top {
display: flex;
flex: 1 1 100%;
padding-bottom: 1rem;
}
#image {
flex: 0 1 50%;
margin: auto;
padding: 3rem;
background-color: #ccc;
text-align: center;
}
#Bottom {
flex: 1 1 100%;
}
#map {
padding: 5rem;
background-color: green;
text-align: center;
}
If, for some reason you cannot use flexbox you can achieve this easily. The main trick is to add an element to act as a wrapper to the image, set a height/width to this element and then set the max-width/max-height on the image to 100%. This way it will scale without deforming.
To achieve occupying each 50% of the vertical size of the screen you can set the height to 50vh.
#map {
background-color: green;
height: 100%;
}
.section {
height: 50vh;
}
.img-container {
width: 100%;
text-align: center;
}
.sample-img {
max-width: 100%;
max-height: 100%;
}
<div id="container">
<div id="Top div" class="section img-container">
<img class="sample-img" src="https://via.placeholder.com/180" alt="image" />
</div>
<div id="Bottom div" class="section">
<div id='map'>Map</div>
</div>
</div>

Absolute scrollable div inside flex container without fixed height, is it possible?

How do I set a div as scrollable (absolute) without fixed height filling entire view, while inside a flex-box?
(https://imgur.com/7v5OFas)
(typo at the right section, its fixed width, the only height expected is to be fullpage everything)
https://codepen.io/anon/pen/oJyOOp?editors=1000
(if I add height to the relative parent of the red section, it works, but I cant have a fixed height. Adding 100% from html to the relative parent also works, but I can't also do that.)
currently it goes:
<div style="display:flex">
<div style="flex-grow:1">
<div style="display:flex">
<div style="width:45px...">
....
</div>
<div ...header code>
....
</div>
<div style="flex-grow:1; top:70px; position: relative">
<div style="position: absolute; top:0; left:0; right:0; bottom: 0; overflow: auto>
</div>
</div>
</div>
</div>
<div style="width:45px...">
....
</div>
</div>
It ends up filling the header height.
I would drop the idea of absolute content if its not necesarry and try something similiar to:
html, body {
min-height: 100%;
height: 100%;
margin: 0;
}
.container{
background: blue;
display: flex;
height: 100%;
flex-flow: row;
}
.sidebar{
background: red;
height: 100%;
width: 200px;
}
.contentWrapper{
display: flex;
flex-flow: column;
flex: 1;
}
.header {
background: yellow;
height: 100px;
width: 100%;
}
.content {
flex: 1;
overflow: auto;
}
.scrollableContent {
height: 3000px;
}
<div class="container">
<div class="sidebar"></div>
<div class="contentWrapper">
<div class="header"></div>
<div class="content">
<div class="scrollableContent">
</div>
</div>
</div>
</div>
Where you basically make every container a flex and the non scalable part of its content will have fix width/height and the other part get flex: 1 which is shorthand for taking rest of the space.

Auto-resize image in flex item

I have the following html :
<div class="main-container">
<h1>A title</h1>
<p>Some text</p>
<div class="sub-container">
<img src="">
</div>
</div>
With the following CSS :
.main-container{
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.sub-container{
flex-grow:2;
background-color: green;
}
Please note that I don't know the size of the container above "main-container". I'm using flex because I want the div in "main-container" to occupy all the remaining space at the bottom.
What I want is to have an image in "sub-container" which fits its parent's size in both directions (height and width). Right now if I add an image into "sub-container" it overflows and doesn't get scaled at all.
I know that flex only works for immediate children (i.e. "sub-container" but not the image inside). I tried to use flex on "sub-container" too, but I couldn't achieve anything satisfactory.
Is this layout you wanted?
Using flex: 1 1 0 to control the sub-container and using width: 100% could make the image to fit the container.
.main-container{
border: 3px solid green;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.sub-container{
flex-grow: 1 1 0;
background-color: green;
display: flex;
}
.sub-container img {
width: 100%;
height: 100%;
}
<div class="main-container">
<h1>A title</h1>
<p>Some text</p>
<div class="sub-container">
<img src="https://picsum.photos/1080/600">
</div>
</div>
You can use this class:
.img-fluid {
max-height:100%;
height:auto;
}
Don't forget to add .img-fluid to your img

100% height div. Parent height determined by image with % width

I have a wrapper div containing a right floated 100% height div and an image.
The image has a width set in %. As you resize the browser window the image height increases and decreased taking with it the height of the wrapper div.
When I set a fixed height on the wrapper div, the right floated 100% height div increases in height as I want it. However, the wrapper div has a dynamic height, set by the current height of the image and the 100% height div, in this instance does not resize vertically as you'd expect.
Is what I'm trying to do achievable?
Here's a pen: http://codepen.io/fraserhart/pen/qiFmb
<div class="wrapper">
<img src="http://i.imgur.com/7v619Ip.jpg" />
<div class="grid">
<section class="row">
<p>Home</p>
</section>
<section class="row">
<p>Looking For Care</p>
</section>
<section class="row">
<p>Working For Us</p>
</section>
<section class="row">
<p>Professionals</p>
</section>
<section class="row">
<p>Who We Are</p>
</section>
<section class="row">
<p>Find a Branch</p>
</section>
</div>
<div class="clear-fix"></div>
</div>
.wrapper{
background:blue;
height:auto;
}
img{
width:60%;
}
.clear-fix{
clear:both;
}
.grid {
display: box;
width:400px;
height:100%;
box-orient: vertical;
background:#ff0000;
float:right;
}
.row {
padding: 20px;
box-flex:1;
background: #ccc;
padding:0px 5px;
border:1px solid #ff0000;
text-align:center;
}
Well, here is one way of doing it, a bit bizarre, probably not to be recommended, but it is a proof of concept, an odd CSS curiosity.
Here is the fiddle: http://jsfiddle.net/audetwebdesign/3tUfC/
Here is the HTML:
<div class="wrapper">
<div class="image-port">
<img src="http://placekitten.com/800/800">
</div>
<div class="content-port">
<div class="grid">
<div class="row">
<img src="http://placekitten.com/100/25">
<p>First...</p>
</div>
<div class="row">
<img src="http://placekitten.com/100/25">
<p>Second...</p>
</div>
<div class="row">
<img src="http://placekitten.com/100/25">
<p>Third...</p>
</div>
<div class="row">
<img src="http://placekitten.com/100/25">
<p>Fourth...</p>
</div>
</div>
</div>
</div>
and here is the CSS:
.wrapper {
outline: 2px dotted blue;
}
.image-port {
outline: 1px dotted blue;
display: table-cell;
width: 60%;
}
.image-port img {
width: 100%;
vertical-align: bottom;
}
.content-port {
display: table-cell;
vertical-align: top;
background-color: wheat;
height: 100%;
width: 40%;
}
.content-port .grid {
}
.content-port .row {
border-top: 2px solid blue;
position: relative;
background-color: rgba(255,255,255,0.5);
overflow: auto;
}
.content-port .row:first-child {
border-top: none;
}
.content-port .row img {
width: 100%;
display: block;
visibility: hidden;
}
.content-port .row p {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: 0 0 0 0;
padding: 10px;
}
How It Works
A .wrapper block contains two table-cell elements: .image-port and .content-port,
with relative widths of 60% and 40% respectively. This avoids the problem of having the grid jump beneath the image for small window sizes.
In the .image-port, let the img scale to 100% width to get a good view of the image.
In the .content-port block element, set the position: relative, and optionally, overflow and a few other properties for visual design.
Here is the trick: in each .row, place a image with a certain aspect ratio. I created four rows so my image as a 4:1 aspect ratio. Set the .row img width to 100% and set the visibility: hidden so that the image takes up flexible space but is out of the way. This will allow each row row to change in size as you re-size the window.
Next, place your content in the .row, for example, a p. the content element is position: absolute such that it takes up the full width and height of the .row parent element (set the offset properties to zero).
The rows now have a height that scales with the width of the window. This approach has some flexibility, and though not perfect, may be useful.
Note that if you stretch the window wide enough, the 100x25 images will be their full width and the .grid will move away from the right edge of the wrapper. You can allow for this by using a larger placeholder image, say 1000x250.
If you make the placeholder image as a transparent gif or png, is should be light weight and since you are using the same image multiple times, the browser should really be making one request for it (I think?).
The Quirk about this approach is that how well the grid expands depends a bit on the aspect ration of the image in the image-port. You will need to experiment a bit and try to optimize the various parameters to get a pleasing layout.

Resources