#18 Responsive Images
Sunday, February 17, 2019
In this article we will see how to deal with a couple of different problems, namely the resolution switching and art direction problems, related to the use of images on our site. We will see how to use the built in browser capabilities to dynamically switch to the appropriate image based on the device the user is using to visit our site.
Parts
- Part 29: Offset Pager Urls
- Part 28: Offset Pager Start
- Part 27: Mock Context Builder
- Part 26: Mock Repository
- Part 25: Mock Async
- Part 24: Picture Tag Helper
- Part 23: Img DPR Tag Helper
- Part 22: Img Responsive Tag Helper
- Part 21: Img Optimized Display
- Part 20: Img Optimization
- Part 19: Img Lazy Loading
- Part 18: Img Responsive
- Part 17: Bottom Nav
- Part 16: Main Nav Cookie
- Part 15: Main Nav Mobile
- Part 14: Main Nav Search
- Part 13: Main Nav Auth
- Part 12: Main Nav Anchors
- Part 11: Main Nav Logo
- Part 10: Search Results
- Part 9: Search Manager
- Part 8: Search Start
- Part 7: Seeding the Database
- Part 6: Domain Database
- Part 5: Emailing Exceptions
- Part 4: Mailkit
- Part 3: View Renderer
- Part 2: Upgrade to 2.1
- Part 1: Quick Start
The page model
- WebUi
- Pages
- Responsive-Images.cshtml.cs
- Pages
The first thing we are going to do is create a razor page where we can explore a couple different problems we
may encounter when dealing with images and their solutions. To do this we need to have a page model that we
can use to easily switch between them (a). We will use the
Problem
property to specify the type of problem and the
Query
property to explore the solutions.
Responsive-Images.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace WebUi.Pages {
public class ResponsiveImagesModel : PageModel
{
[BindProperty(SupportsGet = true)] public string Problem { get; set; }
[BindProperty(SupportsGet = true)] public string Query { get; set; }
public void OnGet()
{
}
}
}
The razor page
- WebUi
- Pages
- Responsive-Images.cshtml
- Pages
Now that we have a model we also need a page to use it on (b). The page provides us a basic ui that will make it easier to switch between the problems and their solutions.
Responsive-Images.cshtml
@page
@model WebUi.Pages.ResponsiveImagesModel
@{
ViewData["Title"] = "Responsive Images";
}
@section Scripts {
<environment include="Development">
<script src="~/js/responsive-images.bundle.js"></script>
</environment>
}
<nav class="responsive-image-nav">
<label>Problems</label>
<a class="@( Model.Problem == "resolution-switching" ? "active" : "" )"
href="/responsive-images?problem=resolution-switching&query=initial">Resolution Switching</a>
<a class="@( Model.Problem == "art-direction" ? "active" : "" )"
href="/responsive-images?problem=art-direction&query=large">Art Direction</a>
</nav>
@if (Model.Problem == "resolution-switching")
{
<nav class="responsive-image-nav">
<label>Resolution</label>
<a class="@( Model.Query == "initial" ? "active" : "" )"
href="/responsive-images?problem=resolution-switching&query=initial">Initial</a>
<a class="@( Model.Query == "different-sizes" ? "active" : "" )"
href="/responsive-images?problem=resolution-switching&query=different-sizes">Different Sizes</a>
<a class="@( Model.Query == "same-size" ? "active" : "" )"
href="/responsive-images?problem=resolution-switching&query=same-size">Same Size</a>
</nav>
if (Model.Query == "initial")
{
}
else if (Model.Query == "different-sizes")
{
}
else if (Model.Query == "same-size")
{
}
}
else if (Model.Problem == "art-direction")
{
<nav class="responsive-image-nav">
<label>Art</label>
<a class="@( Model.Query == "large" ? "active" : "" )"
href="/responsive-images?problem=art-direction&query=large">Large</a>
<a class="@( Model.Query == "small" ? "active" : "" )"
href="/responsive-images?problem=art-direction&query=small">Small</a>
<a class="@( Model.Query == "picture" ? "active" : "" )"
href="/responsive-images?problem=art-direction&query=picture">Picture</a>
</nav>
if (Model.Query == "large")
{
}
else if (Model.Query == "small")
{
}
else if (Model.Query == "picture")
{
}
}
Initial styling
- WebUi
- Source
- pages
- responsive-images.page.scss
- responsive-images.page.scss
- pages
- Source
The last thing to do before we get started with the problem at hand is to add just a little bit of styling to our page (c).
responsive-images.page.scss
@import "../../sass/_non-rendering";
$blue: #0984e3 !default;
$dark-gray: #333 !default;
$light-gray: #ddd !default;
.responsive-image-nav {
background-color: $light-gray;
display: flex;
border-bottom: 1px solid $dark-gray;
a, label {
@include padding(1em 1em);
}
label {
min-width: 110px;
background-color: $blue;
margin: 0;
color: white;
}
a {
display: block;
color: $dark-gray;
text-decoration: none;
&.active {
color: white;
background-color: $dark-gray;
}
}
}
Basic image tag
- WebUi
- Pages
- Responsive-Images.cshtml
- Pages
To start with we will just add a typical image tag to our page (d). For some images if we add a larger image by default and it gets scaled down by the size of the display the image is still readable and for some images it would not be. But even if it is still readable there is a good chance that we are slowing down our site unnecessarly by serving an image that is too large for the device.
Responsive-Images.cshtml
...
@if (Model.Problem == "resolution-switching")
{
...
if (Model.Query == "initial")
{
<div class="image-container">
<img src="/images/responsive-images/woman-balloon-chair-dark-800w.jpg"
alt="Woman sitting on a chair beside a balloon">
<div class="image-caption">
<p>Photo by Daria Shevtsova from Pexels</p>
<p>https://www.pexels.com/photo/woman-sitting-on-chair-beside-balloon-1391580/</p>
</div>
</div>
}
...
}
...
Basic styling for our images
- WebUi
- Source
- responsive-images
- responsive-images.page.scss
- responsive-images
- Source
Next up we are going to add just a little bit of styling (e).
responsive-images.page.scss
...
.image-container {
@include margin(1em auto);
display: table;
picture, img {
display: block;
}
picture {
@include margin(null null 0.5em null);
}
.image-caption {
display: table-caption;
caption-side: bottom;
}
&.same-size {
img {
width: 320px;
}
}
}
...
Resolution Switching: Different Sizes
- WebUi
- Pages
- Responsive-Images.cshtml
- Pages
There are a couple of different approaches that you can take when you want to show the same image content for everyone. The first one is show the image at a lower resolution for devices with smaller viewports. In this example we will show the image at 320px, 480px, and 800px width using breakpoints set at the same values (f).
Responsive-Images.cshtml
...
@if (Model.Problem == "resolution-switching")
{
...
else if (Model.Query == "different-sizes")
{
<div class="image-container">
<img srcset="/images/responsive-images/woman-balloon-chair-dark-320w.jpg 320w,
/images/responsive-images/woman-balloon-chair-dark-480w.jpg 480w,
/images/responsive-images/woman-balloon-chair-dark-800w.jpg 800w"
sizes="(max-width: 320px) 320px,
(max-width: 480px) 480px,
800px"
src="/images/responsive-images/woman-balloon-chair-dark-800w.jpg"
alt="Woman sitting on a chair beside a balloon">
<div class="image-caption">
<p>Photo by Daria Shevtsova from Pexels</p>
<p>https://www.pexels.com/photo/woman-sitting-on-chair-beside-balloon-1391580/</p>
</div>
</div>
}
}
...
Resolution Switching: Same Size
- WebUi
- Pages
- Responsive-Images.cshtml
- Pages
Next up is the case where we want to again show the same image content but we want to show a higher resolution image for higher resolution displays such as retina displays. In this case we fix the size of the image by specifying the width in css and then specify which image should be shown in a 1x and 2x dpr device (g).
Responsive-Images.cshtml
...
@if (Model.Problem == "resolution-switching")
{
...
else if (Model.Query == "same-size")
{
<div class="image-container same-size">
<img srcset="/images/responsive-images/woman-balloon-chair-dark-320w.jpg,
/images/responsive-images/woman-balloon-chair-dark-640w.jpg 2x"
src="/images/responsive-images/woman-balloon-chair-dark-640w.jpg"
alt="Woman sitting on a chair beside a balloon">
<div class="image-caption">
<p>Photo by Daria Shevtsova from Pexels</p>
<p>https://www.pexels.com/photo/woman-sitting-on-chair-beside-balloon-1391580/</p>
</div>
</div>
}
}
...
Art Direction: Large
- WebUi
- Pages
- Responsive-Images.cshtml
- Pages
In this section we will focus on showing modified images based on the resolution of the device. To begin with we will just show the large image (h).
Responsive-Images.cshtml
...
else if (Model.Problem == "art-direction")
{
...
if (Model.Query == "large")
{
<div class="image-container">
<img src="/images/responsive-images/abandoned-architecture-bungalow-2560w.jpg"
alt="Abandoned cabin in the woods">
<div class="image-caption">
<p>Photo by Mateas Petru from Pexels</p>
<p>https://www.pexels.com/photo/wooden-house-on-a-forest-673788/</p>
</div>
</div>
}
...
}
Art Direction: Small
- WebUi
- Pages
- Responsive-Images.cshtml
- Pages
Next up we will take a look at the image after it has been cropped for display on a smaller device (i).
Responsive-Images.cshtml
...
else if (Model.Problem == "art-direction")
{
...
else if (Model.Query == "small")
{
<div class="image-container">
<img src="/images/responsive-images/abandoned-architecture-bungalow-1200w.jpg"
alt="Abandoned cabin in the woods">
<div class="image-caption">
<p>Photo by Mateas Petru from Pexels</p>
<p>https://www.pexels.com/photo/wooden-house-on-a-forest-673788/</p>
</div>
</div>
}
...
}
Art Direction: Picture
- WebUi
- Pages
- Responsive-Images.cshtml
- Pages
Lastly we can use the picture tag to specify which image should be shown again based on the size of the device (j).
Responsive-Images.cshtml
...
else if (Model.Problem == "art-direction")
{
...
else if (Model.Query == "picture")
{
<div class="image-container">
<picture>
<source media="(max-width: 1199px)"
srcset="/images/responsive-images/abandoned-architecture-bungalow-1200w.jpg">
<source media="(min-width: 1200px)"
srcset="/images/responsive-images/abandoned-architecture-bungalow-2560w.jpg">
<img src="/images/responsive-images/abandoned-architecture-bungalow-1200w.jpg"
alt="Abandoned cabin in the woods">
</picture>
<div class="image-caption">
<p>Photo by Mateas Petru from Pexels</p>
<p>https://www.pexels.com/photo/wooden-house-on-a-forest-673788/</p>
</div>
</div>
}
}