- Делаем картинку такой же высоты как соседний блок с помощью flex и object-fit
- Рабочий пример, как растянуть картинку на высоту соседнего блока
- Упрощенный код SCSS для блоков одинаковой высоты
- Adaptive Photo Layout with Flexbox
- Flexible CSS cover images
- Aspect ratio
- Maximum dimensions
- Background image
- Final result
- Adaptive Photo Layout with Flexbox
Делаем картинку такой же высоты как соседний блок с помощью flex и object-fit
Задача такая, слева размещена картинка, а справа блок, внутри которого какой-то контент или другие блоки. Нужно сделать так, чтобы картинка была такой же высоты как и блок справа на любом разрешении экрана.
Рабочий пример, как растянуть картинку на высоту соседнего блока
Упрощенный код SCSS для блоков одинаковой высоты
// reset for img img < max-width: 100%; height: auto; vertical-align: bottom; >.line < display: flex; justify-content: space-between; max-width: 768px; margin: 20px auto; >.left < flex: 0 1 calc(50% - 10px); max-width: calc(50% - 10px); .pic-holder < height: 100%; >.pic < width: 100%; height: 100%; object-fit: cover; >> .right < flex: 0 1 calc(50% - 10px); max-width: calc(50% - 10px); display: flex; flex-direction: column; justify-content: space-between; .item < padding: 40px 20px; text-align: center; background-color: #ccc; margin-bottom: 20px; &:last-child < margin-bottom: 0; >> >
Если высота картинки больше чем высота соседнего блока, то картинка может выходить за границы, и поэтому в моем примере элементы внутри соседнего блока растягиваются по высоте, что бы и левый, и правый блоки имели одинаковую высоту.
Задача — выводить в десктопной версии несколько слайдов с определенным дизайном, а в мобильной версии…
Мой репозиторий — https://github.com/DenisShapkun/images-optimization. Используем вместо Tinypng десктопный вариант Gulp. Пакетная оптимизация изображений формата PNG,…
В общем, очередная секретная разработка для ускорения процесса создания сайтов. Обычно для верстки я использовал…
CSS генератор треугольников, иногда приходится применять, чтобы создать уголки для каких-то элементов с помощью CSS….
Adaptive Photo Layout with Flexbox
Let’s take a look at a super lightweight way to create a horizontal masonry effect for a set of arbitrarily-sized photos. Throw any set of photos at it, and they will line up edge-to-edge with no gaps anywhere. The solution is not only lightweight but also quite simple. We’ll be using an unordered list of images and just 17 lines of CSS, with the heavy lifters being flexbox and object-fit .
I have two hobbies: documenting my life with photos, and figuring out interesting ways to combine CSS properties, both old and new. A couple of weeks ago, I attended XOXO and shot a ton of photos which I narrowed down to a nice little set of 39. Wanting to own my content, I’ve spent the past couple of years thinking about putting together a simple photo blog, but was never able to nail the layout I had in mind: a simple masonry layout where photos fill out rows while respecting their aspect ratio (think Photos.app on iOS, Google Photos, Flickr…). I did some research to see if there were any lightweight, non-JavaScript options, but couldn’t find anything suiting my needs. Facing some delayed flights, I started playing around with some code, limiting myself to keep things as simple as possible (because that’s my definition of fun).
- Flexbox is great for filling up rows by determining cell width based on cell content.
- This meant the images (landscape or portrait) all needed to have the same height.
- I could use object-fit: cover; to make sure the images filled the cells.
In theory, this sounded like a solid plan, and it got me a result I was about 90% happy with.
Note: 40vh seemed like the best initial approach for desktop browsers, showing two full rows of photos at a reasonable size, and hinting at more below. This also allowed more photos per line, which dramatically improves the aspect ratios.
Combined with this bit of CSS:
Note: There’s no science in using “10” here. In all my testing, this delivered the best results.
There are some considerations to keep in mind when working in different viewport orientations.
If your viewport is taller than it is wide, this approach limits the amount of photos per line thus messing up their aspect ratios. To solve this, you can make the photo rows less tall with this simple media query:
To help with small devices in landscape, increasing the height of photos helps to see them as large as possible:
Smaller Screens + Portrait
Most phones aren’t wide enough to allow flexbox to properly do its job without miniaturizing the photos, so here I opted to not try to fit multiple photos per line. Still, it’s worth setting a maximum height here so you’ll at least have a hint at the next photo in the list.
@media (max-aspect-ratio: 1/1) and (max-width: 480px) < ul < flex-direction: row; >li < height: auto; width: 100%; >img < width: 100%; max-height: 75vh; min-width: 0; >>
This approach doesn’t fully respect the aspect ratios of photos (but it’s close) and occasionally leads to some weird results, but I absolutely love the simplicity and flexibility of it all. Want to have your gallery scroll horizontally instead of vertically? A couple of tweaks will allow you to do this. Are there 1,000 photos in the gallery or just one? It’ll all look good. Unclear about aspect ratios? Flexbox is your best friend. Take another look at the demo if you haven’t yet, and let me know what you think!
Depending on the size of these photos, a page like this can grow to multiple megabytes real quick. On the blog I’m working on, I’ve added loading=»lazy» to help with this. With that attribute in place on the images, it only loads photos once you approach them while scrolling. It’s supported just in Chrome for now, but you could roll your own more supported technique.
Flexible CSS cover images
The way that the cover image scales, and changes aspect ratio, is illustrated in the following diagram.
The cover image component must:
- render at a fixed aspect ratio, unless specific maximum dimensions are exceeded;
- support different aspect ratios;
- support max-height and max-width ;
- support different background images;
- display the image to either fill, or be contained within the component;
- center the image.
Aspect ratio
The aspect ratio of an empty, block-level element can be controlled by setting a percentage value for its padding-bottom or padding-top . Given a declaration of padding-bottom:50% (and no explicit height ), the rendered height of the element will be 50% of its width.
.CoverImage
padding-bottom: 50%;
>
Changing that padding value will change the aspect ratio. For example, padding of 25% results in an aspect ratio of 4:1 , padding of 33.333% results in an aspect ratio of 3:1 , etc.
Maximum dimensions
The problem with using this aspect ratio hack is that if the element has a max-height declared, it will not be respected. To get around this, the hack can be applied to a pseudo-element instead.
.CoverImage:before
content: "";
display: block;
padding-bottom: 50%;
>
Now the main element can take a max-height . It should also clip the pseudo-element overflow.
.CoverImage < display: block; max-height: 300px; max-width: 1000px; overflow: hidden; > .CoverImage:before
This aspect ratio pattern is provided by the FlexEmbed component for SUITCSS. That component is primarily for responsive video embeds, but it’s flexible enough to be useful whenever you need an element rendered at a predetermined aspect ratio. It comes with modifiers for 2:1 , 3:1 , 16:9 , and 4:3 aspect ratios. The cover image component can extend the FlexEmbed component.
Background image
The cover image is applied as a background image that is sized to cover the entire area of the element. This makes sure the image is clipped to fit the aspect ratio of the element.
.CoverImage
.
background-repeat: no-repeat;
background-size: cover;
>
If you want different cover images for different instances of the component, they can be applied via the style attribute.
style="background-image: url(cover.jpg)">
The image can be fully centered by using background positioning and block centering. This makes sure that the image is centered in the element, and that the element is centered within its parent (when it reaches the max-width value).
.CoverImage < . background-position: 50%; background-repeat: no-repeat; background-size: cover; margin: 0 auto; >
Final result
If you depend on the FlexEmbed module, the amount of additional code required is minimal. (See the demo for all the code, including the FlexEmbed dependency.)
/**
* Requires: suitcss/flex-embed
*/
.CoverImage
background-position: 50%;
background-repeat: no-repeat;
background-size: cover;
margin: 0 auto;
max-height: 300px;
max-width: 1000px;
>
div class="CoverImage FlexEmbed FlexEmbed--3by1"
style="background-image:url(cover.jpg)">
div>
You can add further customizations, such as setting the accompanying background color, or providing a means to switch between the cover and contain keywords for background-size .
Nicolas lives and works in California. He’s on Threads and shares software using GitHub.
Adaptive Photo Layout with Flexbox
Let’s take a look at a super lightweight way to create a horizontal masonry effect for a set of arbitrarily-sized photos. Throw any set of photos at it, and they will line up edge-to-edge with no gaps anywhere. The solution is not only lightweight but also quite simple. We’ll be using an unordered list of images and just 17 lines of CSS, with the heavy lifters being flexbox and object-fit .
I have two hobbies: documenting my life with photos, and figuring out interesting ways to combine CSS properties, both old and new. A couple of weeks ago, I attended XOXO and shot a ton of photos which I narrowed down to a nice little set of 39. Wanting to own my content, I’ve spent the past couple of years thinking about putting together a simple photo blog, but was never able to nail the layout I had in mind: a simple masonry layout where photos fill out rows while respecting their aspect ratio (think Photos.app on iOS, Google Photos, Flickr…). I did some research to see if there were any lightweight, non-JavaScript options, but couldn’t find anything suiting my needs. Facing some delayed flights, I started playing around with some code, limiting myself to keep things as simple as possible (because that’s my definition of fun).
- Flexbox is great for filling up rows by determining cell width based on cell content.
- This meant the images (landscape or portrait) all needed to have the same height.
- I could use object-fit: cover; to make sure the images filled the cells.
In theory, this sounded like a solid plan, and it got me a result I was about 90% happy with.
Note: 40vh seemed like the best initial approach for desktop browsers, showing two full rows of photos at a reasonable size, and hinting at more below. This also allowed more photos per line, which dramatically improves the aspect ratios.
Combined with this bit of CSS:
Note: There’s no science in using “10” here. In all my testing, this delivered the best results.
There are some considerations to keep in mind when working in different viewport orientations.
If your viewport is taller than it is wide, this approach limits the amount of photos per line thus messing up their aspect ratios. To solve this, you can make the photo rows less tall with this simple media query:
To help with small devices in landscape, increasing the height of photos helps to see them as large as possible:
Smaller Screens + Portrait
Most phones aren’t wide enough to allow flexbox to properly do its job without miniaturizing the photos, so here I opted to not try to fit multiple photos per line. Still, it’s worth setting a maximum height here so you’ll at least have a hint at the next photo in the list.
@media (max-aspect-ratio: 1/1) and (max-width: 480px) < ul < flex-direction: row; >li < height: auto; width: 100%; >img < width: 100%; max-height: 75vh; min-width: 0; >>
This approach doesn’t fully respect the aspect ratios of photos (but it’s close) and occasionally leads to some weird results, but I absolutely love the simplicity and flexibility of it all. Want to have your gallery scroll horizontally instead of vertically? A couple of tweaks will allow you to do this. Are there 1,000 photos in the gallery or just one? It’ll all look good. Unclear about aspect ratios? Flexbox is your best friend. Take another look at the demo if you haven’t yet, and let me know what you think!
Depending on the size of these photos, a page like this can grow to multiple megabytes real quick. On the blog I’m working on, I’ve added loading=»lazy» to help with this. With that attribute in place on the images, it only loads photos once you approach them while scrolling. It’s supported just in Chrome for now, but you could roll your own more supported technique.