Design

Background Images for Ionic 4

A common UI design that is applied to many mobile applications is to have an image serve as the background. This is a question that I see asked multiple times on the Ionic Forums, so I thought I would take a moment and outline the best approach to achieving this effect.

If you only need to attach your image to a specific page, just go to that page’s .scss file and define the –background variable. Here, I will set the image to reference a bg.jpg file I have in my assets directory, as well as set the parameters of how it should be rendered.

ion-content {
  --background: url(../../assets/bg.jpg) no-repeat center/cover fixed;
}

Note, the path to the asset is relative to the page’s directory.

But what if you wanted that image to be used across all of the pages? You could then move the code to the global.scss file. Since this is now being applied a global level, we need to adjust the url path:

ion-content {
  --background: url(/assets/bg.jpg) no-repeat center/cover fixed;
}

This initially will work, but watch closely when we transition from screen to screen. The background image will either shift or blank out for a moment.

ezgif.com-video-to-gif

This is due to the fact that the ion-content component that we have targeted with our CSS, is being destroyed when we navigate from screen to screen. To solve this we need to remember that Ionic at its heart is still just the web. So rather than focus on Ionic’s web components, we can think about what other HTML elements we might be able to use.

The answer is to have the body tag be the element that we attach our image to. So, in the global.scss file we can add:

body {
  background: url(/assets/bg.jpg) no-repeat center/cover fixed;
}

However, if you just made that change, you will find that the image no longer is visible. This is because the default values for ion-content are being applied. Meaning, the fill color is now being used, thus covering our image. To solve this, we need to override that with:

ion-content {
  --background: none;
}

And now we will have a nice static background for the application.

ezgif.com-video-to-gif (1)

Advertisements

Centering Gallery Elements

Recently, I was rebuilding one of my websites to be responsive. It is important to take advantage of the capabilities of modern browsers and be responsive, to support the growing use of the site on mobile devices. One portion of the design was a set of image gallery pages. These pages are pretty straight-forward, up to 5 columns of photos per row centered within the width of the page. As the window width reduces, the number of columns reduces. Again, nothing out of the ordinary with this design.

figure1

Block version of the design

 

I began by centering the containing div by setting the CSS properties of margin-left and the margin-right values to “auto”. That positioned the containing div correctly and it responded as expected as the browser width was changed. However, as the width of the window reduced, the thumbnails would begin to start to flow down to the next row, but they would display centered within the containing div. Not exactly the design I was looking for.

Centered elements

Centered elements

I applied a float:left to the thumbnails, and my centering last row was fixed! However, it introduced a new problem–the thumbnails no longer appeared to be centered as a group within the page. Adding the float to the thumbnails introduced extra spacing between the last column and the right boundary of the containing div.

Highlighting the margin right issue

Highlighting the margin right issue

I knew that had to be solved, so I began looking at many of my favorite tutorial sites, and found nothing. Lots of great samples of gallery pages, but all using the full width of browser in their samples or the thumbnail sizes would adapt to their widths. Nothing seemed to fit my design.

Next, I decided to look at using Flexbox. I had made the choice to only support “modern” browsers, so I knew that I did not need to worry too much about compatibility issues. But the same issues remained as I experimented with the various flex layout options; the last row items would be centered, or the gap on the right existed. Back to the drawing board!

Then I got to thinking about how the layout was computed. Each thumbnail would take the same fixed amount of space. Each would position itself to the left due to setting the float property to left. If the thumbnail did not have enough space within the width of the container, it would move to the next row. Float 101, right? But how did it know the space it had? I only defined the containing div to have a max-width and to center itself, and the width would vary based on the width of the window. It then struck me that if the width of the containing div matched the number of allowable columns, then there would not be extra space along the right.

Eureka!

If I can set the containing div to match my column widths, that container will still be properly centered. So I calculated the computed widths for 2,3,4, and 5 columns of thumbnails. So, when the browser’s width reaches specific widths, the containing div’s width is fixed to match the allowable number of columns. With a fixed width instead of a dynamic width, it can be properly centered on the page. Design problem solved!
The resulting CSS looks like this

<style> 
 #photoMenu {
   margin-left: auto;
   margin-right: auto;
   height: auto;
   min-height: 220px;
 }
 
 .thumbnail {
   position: relative;
   border: 5px solid #ddd;
   float: left;
   margin: 20px;
   width: 160px;
 }
 
 .thumbnail img {
  max-width: 100%;
 }
 
 .thumbnail h3 {
   position: absolute;
   bottom: 0;
   left: 0;
   width: 100%;
   margin: 0;
   text-align: center;
   color: white;
   font: bold 1em/1.5em Verdana, Sans-Serif;
   background: rgb(0, 0, 0);
 }
 
 @media (min-width: 315px) {
   #photoMenu {
     background-color:darkred;
     width: 210px;
   }
 }
 
 @media (min-width: 525px) {
   #photoMenu {
     background-color: darkseagreen;
     width: 420px;
   }
 }
 
 @media (min-width: 735px) {
   #photoMenu {
     background-color: rebeccapurple;
     width: 630px;
   }
 }
 
 @media (min-width: 945px) {
   #photoMenu {
     background-color: bisque;
     width: 840px;
   }
 }
 
 @media (min-width: 1155px) {
   #photoMenu {
     background-color: aqua;
     width: 1050px;
   }
 }
 </style>

For each of the media query breakpoints, I added a background color just to highlight it. Here is what the HTML looks like:

<div id="photoMenu">
  <div class="thumbnail">
    <img src="thumbnail.png" alt="">
    <h3>Title</h3>
  </div>
  <div class="thumbnail">
    <img src="thumbnail.png" alt="">
    <h3>Title</h3>
  </div>
  <div class="thumbnail">
    <img src="thumbnail.png" alt="">
    <h3>Title</h3>
  </div>
  <div class="thumbnail">
    <img src="thumbnail.png" alt="">
    <h3>Title</h3>
  </div>
  <div class="thumbnail">
    <img src="thumbnail.png" alt="">
    <h3>Title</h3>
  </div>
  <div class="thumbnail">
    <img src="thumbnail.png" alt="">
    <h3>Title</h3>
  </div>
  <div class="thumbnail">
    <img src="thumbnail.png" alt="">
    <h3>Title</h3>
  </div>
</div>

You can see the completed sample here.

Little design…

With the upcoming 70th anniversary of the dawn of the atomic age, I am refreshing several of my websites on the subject. The first site I am working on is Trinity Remembered. The new design is now responsive. The images are much larger (and more of them). But one particular page was not quite right. All the other ‘menu’ screens had visual elements, while this one just had the list of available documents. So I spent some time fiddling with it. I tried adding icons before each document to see if that could solve. But in the end, it was as simple as increasing the indents of the sections and adding a thin gray rule under each sub-section was enough. This gave the eye enough clues of how to parse the information without being overwhelmed. Just thought I would share a tiny bit of my design process.

TR_docs_before

TR_docs_after