What do you want to learn?
Skip to main content
Hands-on Responsive Web Design 3: Columns, Flexbox, and Grids
by Paul Cheney
This course will teach you how to implement multiple column layouts using standard divisions, Flexbox, and CSS Grids. You'll also examine CSS shapes for interesting text wrapping.
Start CourseBookmarkAdd to Channel
Table of contents
Hello, my name is Paul Cheney, let me tell you about this series of hands-on responsive design courses. At the heart of developing any responsive website is a thorough knowledge of how use HTML 5, CSS3, and Sass. In Responsive Web Design 3: Columns, Flexbox, and Grids, you will learn the skills you need to lay out pages using a grid with traditional floats and divisions. You will automate this process by leveraging the power of Sass operators. This approach works on all modern and older browsers. In addition, we will explore the new flexbox, which is great for laying out items both horizontally and vertically. We'll then move onto my favorite, CSS grids, which is more for overall page layout. You will learn how simple it is to build any responsive layout using named areas. You will build a mobile music player interface, which includes everything we've covered in this course. As we're moving though the course we'll also learn about image sprites, fonts for icons, clipping paths for images, and wrapping text. When you're finished with this course you will have built several functioning examples, which you can use in your next client project. Please join me as we explore flexbox, grids, icons, and paths in this third of four hands-on responsive design courses from Pluralsight.
Hello, and welcome to another hands-on course from Paul Cheney. This is the third in a series of four in-depth courses on responsive web design. In this course, we will focus on a 12-column grid, flexbox, and my personal favorite, CSS grid, they are awesome. In the first module, we'll make sure you're in the right place with a quick overview. Next I will show you all the projects we will be building in this course. Then we'll get started with the first project. If you want to know how to make a multiple-column grid using Sass, variables, and loops, then you're in the right place. If you want to use CSS for masking images and really interesting text wrapping then I've got you covered. If you want to learn how to use flexbox for real-world projects, then I'm here to give you a hand. If you want to explore the new CSS grids, my personal favorite, then please stay with me. It will be helpful if you have already completed the two previous hands-on courses in this series, before starting this one. We will be doing a little Photoshop, but I will provide you with the images in case you don't have access to Photoshop. As before, you need a text editor, and of course a CSS preprocessor like Koala app. It will also be helpful to have multiple browsers on your computer, as well as a couple of mobile devices on hand for testing your work. Let me give you a quick peek at what we're going to build. Our first project, we'll be creating a traditional row and 12-column setup using floats and column widths. We will also generate 36 lines of CSS using only 3 lines of SCSS; it's pretty cool. We will also use image sprites for our social icons. Next we will look at masking images using CSS and also text wrapping in several different configurations. In this example we will use Font Awesome for our social icons, and you're going to love that. Our third project will be all about flexbox. We'll discover how much easier it is to use than floats and explore which browsers support it. Finally, we will explore my favorite, CSS grids. You're going to be amazed at how powerful they are. We will lay out an entire page using only grids, from the hamburger icon to the footer, for small, medium, and large layouts. We'll then wrap up everything by building the front-end for a mobile music, which will include font icons, CSS grids, and flexbox. So now you know that you're in the right place, and what you'll be building for this course. Now that was a fast introduction, and now we're ready for the 12-column grid and our amazing Sass code.
Twelve Column Grid
Hello, and welcome back. I'm excited to have you here with me for this module. Since we're taking a holistic approach to learning, we're going to not only build the 12-column grid, but also learn about image sprites, which are used as the social icons in this example's header. First, we will explore image sprites, and then review progressive enhancement, then we'll look at several advanced SaaS capabilities, and finally, we'll build a 12-column grid example with social icons as sprites.
An image sprite is a single graphic that has multiple icons in the same image. We then use CSS to show only one icon at a time. One reason we like sprites is the freedom it gives to build any icon that Photoshop can create, unlimited color, unlimited options. It also reduces the number of HTTP requests to a single request by combining all of the icons into a single image, and therefore a single HTTP request. Here's an example of an image sprite. The default position is 0, 0, which is the upper-left corner. The total size of this graphic is 150-pixels tall by 150-pixels wide. Therefore, each icon is 50-pixels square. In order to display a lower image, you need to use negative values. In order to display an image to the right you also need to use negative numbers. So let's jump into our text editor and try this out. I have a copy of this start folder for my demos, and I've got the SpritePractice.png. Let me go ahead and drag that into the images so it's ready to go. I also have my snippets open, which we'll use in a second. My CSS preprocessor is running, and I have my text editor ready to go. So let's jump into our snippets, let's grab this first unordered list, which has a class of blue, bee, and one. I'll paste it in our index file, right here in the middle of the main open and closing tag. Now we're ready to go to the small-default. Once again we're inside the main, right after the h1, let's go ahead and talk to the ul li's on the page. Now this works because there's only one unordered list. So what are the rules that apply to all of these icons? Well, we decided earlier that each icon is 50-pixels tall and 50-pixels wide. We also loaded a single background image, which is going to be used for all three of them. So I'll load it here on the list item. Now this next line is not necessary, but because we're learning I'm going to go ahead and put it in. Background-position, the first value is the horizontal axis, left to right, 0, the second value is the y-axis, or the up and down. Now these are default values. Let's save it, we'll open our index, and here we can see that it is working, and we have red dots for all three of our list items. Now let's come into each individual list item and change it around so that is shows a different sprite. Let's go back to our index, remind ourselves that we're going to talk to the blue class, the bee class, and the one class. Let's go back and look at our graphic. For the blue class we want to show the blue circle. So the X value, or the left to right is correct because it's already showing the circle column, now we just need to go down past the green one to the blue one. So our background-position x-axis is correct, and the y-axis is -100. And there we have the first one showing a blue dot. Now the bee is actually supposed to show the letter B, which is the second column, second row. So that would be background-position, 50 to the right, which is actually -50, and 50 down, which is also -50. We'll check it and see if it works, and sure enough, there's the B. The third one is the number 1, which is the third column over, top item. So the background-position there is going to be -100 from left to right, and 0, which should show the first number. Now, another interesting thing that we can do, is actually change this so that when we hover over this li, we see a different one of the sprite. So let's go down and when we hover over the 1 let's actually show a 2, which is -50px. Now refresh, we mouse over the 1, it becomes a 2. So if you have a sprite icon that you want to change, maybe darken, maybe change from black and white to color, this is how you would do it.
Now let's look at building a 12-column grid. In order to understand why this works let's quickly review progressive enhancement. CSS rows are laid out sequentially in this CSS file, so that the rules for small screens are first, followed by a media query and rules for medium screens, followed by another media query and rules for large screens. For example, we have a plum class in the small CSS, and a purple class in the medium CSS, and an orange class in the large CSS. Now we create a division with a class of plum. And the result is plum on all three screens, no big surprise there. Now we add a second class of purple to this same division, and on medium and large screens the color switches to purple. This is because the rules on the medium screen override the rules on the small screen, because they are later in the CSS file. Of course if we add a third class of orange to the division then the color is different for all three screens. Let's open our text editor and take a look at this in a browser. I've created a plum class in small SCSS and increased the font size so we can see it. I've created a purple class in the medium SCSS, and an orange class in the large SCSS. Now we create the division and assign a class of plum, and it is plum on all the screens. When we add the other two it changes color for each different screen. This is the principle we will use when we build our 12-column grid.
Project - Social Icons
Make sure you have a fresh copy of the start folder, and the socialSprites.png file, which you should drag into the images folder. I've also got my snippets.txt up, which has this unordered list with the class of social. Let me copy that. In my text editor I've got the index.html open, and inside the header, right after the h2, Stories that Move You, I'm going to paste that code from my snippets file. Save it, hit Refresh, and we can see our social icon unordered list in blue. For the small screens I'm going to display the social icons from left to right underneath this Stories that Move You heading too. We really don't need these letters, so we can take those out. In our _small-default.scss, on about line 34, we have a section inside of the header for the social icons. So let's start with talking to the list items, so ul.social li. We want all of the list items to remove that dot, which you can see just barely over here on the left side. So we'll turn the list-style-type to none. Now those dots are gone. We want all of these to float to the left, so that they stack left to right instead of top to bottom. Because there's four social icons, and we want them to fill the full screen width, 100 divided by 4 is 25%. Now let's talk to the anchors that live inside each individual list item. Whenever you have an anchor the first thing you need to do is display it as a block. We want the icon to be centered inside the anchor, so let's set the margin to 0, top and bottom, and auto, left and right. We also need to specify the background image as the socialSprites.png file. If we return to our start file and we open the socialSprites icon we can see the width is 270, and we have 6 social icons. We'll take 270 and we'll divide it by 6, that tells the us the width of each one is 45 pixels. Now you can't really see it, but there's a white version of the icon beneath each of these, that's why the height is 90, because there's 2. So it's actually 45-wide by 45-tall. Now we'll refresh our page, and we can see this icon appearing for all four of our sprites. So now we're ready for the next section, which is to specify a different icon for Twitter, YouTube, Facebook, and Google+. Ul.social, space, so we're looking for the child, .twitter, anchor, and we want the background position. So Twitter is the third icon over, Facebook starts at -45, and Twitter starts at -90; -90px, space, and we want the wide version of the icon, which is the second row, so we have to go down, -45 pixels. Let's save that and see if it works for the Twitter icon. Sure enough, the second one is ready to go. Let's copy that. The second icon we'll take care of if the youtube, third one is facebook, and the fourth one we'll use is googleplus. Of course all of these class names come directly from these class names here. So now if we do our research, YouTube is the sixth one over, so you times that out, and you get -225px. Facebook is the second one, so it's a -45, Google+ is the fifth one over, so it's -180 pixels. Save it, hit Refresh, and there are all of our white icons now appearing on our dark-brown background. Now we're not done, because when we mouse over, we want to show the top row of icons, the ones that are full color. So let's copy these. When we :hover over each anchor, then we're going to change the background position so it pulls from the top row, which is at 0, instead of the second row, which is the -45. So we put in some 0s here, save it, hit Refresh, and now I mouse hover, we're getting the full-color version of each of these logos. Now that works great for our small screens. When we go to our medium screens, we want them to pop up here to the right of our World News, so they don't take quite as much space. Let's open our medium.scss file, once again we're working inside the header, in order to position something absolutely we must position its parent relative. So in the header we need to add position: relative. it allows us to go into the ul.social and specify its position as absolute. Now where do we want it positioned? We want the bottom of it to be .5rem up. And we want to move it from the left over to the right, but we don't want it right against the edge, we want it to be 2% away, so we're going to throw in our gutter variable, which is 2%, save it, there it is over there. We'll do one more thing here, just to be safe on all browsers. If you remember in our small, we set the width to 25% for the list items. So we're going to come over to our medium, and we're going to set our ul.social li to have a width of auto. That will just make sure it works correctly everywhere. Here we have our small version, where they're full-width, all the way up to our large screens where they hang out over here at the right side.
Project - Columns Part 1
Now that the social icons are done, we're ready to do the 12-column grid. Here in my _small-default.scss file I'm going to go inside of the main and create a brand-new section for the column layout. Now this is a fairly significant block of code, so I'm going to identify it clearly with a nice comment. Whenever we do column/row layouts we need to specify stuff for the row, stuff for the column, and then other classes that handle the width. So let's start with .row. Well all of the rows need to clear anything that's above them, that's really all that the row does, makes sure that things don't get mixed up between different rows. Every column is going to have a class of column. There's one thing that columns do across the board, regardless of their width, and that is they have padding on the left and right sides to separate them from each other. Now we're ready for this awesome math SaaS magic that we looked at earlier. So let's start with an @ sign. We'll do a for loop, we'll create our own variable called i. And then we'll go from 1 through 12, because we're doing a 12-column grid. We'll create another variable called w, it stands for width, and we'll do some math on it. We'll start by taking the variable i, which is going to start at 1 and count up to 12, and we'll divide it by 12, which is the number of columns that we want. And then we have to give it a value, so we'll multiply it by 100%. Now we're going to use interpolation to create a class. So the class is going to be .small-, and we want this to be small-1 through small-12. So once again, we have to interpolate by using #, left and right curlies, and inside of that we put our variable i. So it'll be small-1, small-2, etc. And then, inside another set of curlies we do our declarations of width, and our width is this variable right here, $w, and we also want to float all of these to the left. And that should do it. Let's save it. Let's take a look at our output CSS, and we can see here starting on line 178 we've got our row, then we have our column, and then we have all 12 of our small-1 through 12 classes, created dynamically, the math is perfect, and these are awesome and ready to go. Well that will work great for small screens, but we need to do the same thing now with medium screens. So let's jump back to our small. Let's copy this, jump to our _medium.scss, and once again, inside of the main tag we'll create a new section with a nice big comment. Now the row is not changing, the column is not changing, actually the only thing that changes is our class designation, instead of small we'll use medium. Once again, medium-1 through 12. Save it, open up the output of our CSS preprocessor, there's our small, and there's our medium. Once again, medium-1 through medium-12. Let's copy this COLUMN LAYOUT section, we'll go to large, and simply change the word medium to large. So now with these three little, tiny blocks of code, we have generated tons and tons of CSS that is accurate in measurement to very small percentages. if you were to try and type all of these values by hand, you would go crazy after a while. Now that we're ready to do our HTML, we're going to set up a series of rows and columns. Each row will contain multiple columns and will be set up to always follow any rows above it. So this h1 Breaking News actually is going to live inside of its own row/column combination. As you start creating divs within divs and have multiple columns within a row, it's going to be very important that you identify with comments the end of each column and the end of each row. Now that this is set up let's come back to our browser. Notice before I refresh that the B on Breaking is touching the left edge. Once I refresh, the space that's applied to each column of 2% is now giving me my 2% space to the left of the B. So now that that row/column combination is done, and there's only going to be one column in that one, let's do a second example. This time we'll do a h2 and we'll throw in some filler text. This particular example is going to have four news stories, so let me copy the column, paste it a second time, a third time, and a fourth time. And if we want we could come in here and identify these as News Items 1 through 4. Now for the small screens, we want each of these to be full-width, in other words, 12 of 12. So we'll do a small-12 as the second class that's assigned to each of these divisions. When we go to the medium screen, we're going to display them side by side. So each one for medium will be 6 of 12, in other words, 50%. Let's check our work, hit Refresh. We return to the small, we can see each one is stacked. They're kind of running into each other a little bit, so let me quickly jump back to the small, I've got an h1 here, let me come in and do an h2, and we'll just do some padding-top to separate it a little bit, and it looks a little bit better. So there's our News Items on small screens, all stacked, 12 of 12. We go to medium screens, they're now side by side. We go to large screens, they're still side by side because we haven't specified anything different, but we could, we could go to our HTML, we'll add another class of large-3, 3 of 12 is 25%. and there's our 3 of 12, medium, and full-screen.
Project - Columns Part 2
Let's press this a little bit further, and let's add an additional two columns. So there's number 5, there's number 6, and we'll switch it to 5 and 6. In this example, we're going to set the small to 50%, so that would be 6 of 12, we're going to set the medium screens to display 3 across, so that's 4 of 12, and then the large screens will be 2 of 12 so we can get 6 across, all 6 showing. So let me copy those three additional classes, paste them down here. In our small screens, when we refresh, we now have two wide, we go to medium, we've now got three showing up, and of course in large, we've got six showing up. So you can see how easy it is to set up different numbers of columns once you get all the CSS in place. Now in our next example we're going to do something a little different. I've reduced this to 3 columns within this row, and we're going to start by displaying the smallest ones at full width, but when we go to medium I'm going to leave the first item at full width, and then the next 2 are going to be 6 of 12, in other words 50%. And for now I'm not going to change it for the large, I'll just leave it the same as the medium. So here we go, everything's full width. In medium now we can see the top is kind of like a leading article, and then we've got two smaller ones beneath it, which continues all the way through there. Now we could come into the large, and we could take the first item and make it 50%, and then do 25% for the next 2. Now that looks a little odd, but that's because we're missing a photograph in the primary news item. In the demos for this unit I've got a photograph called housing, if you grab that and drop it in your images folder, then we can come into our small and we can do a figure, and an image, with a source, and then we'll go to our _small-default, and we'll talk to the figure, and set its width to 33% of its container, in other words the column. And then we'll float it to the right. And of course, to make this work we need to go to the second part, figure img width: 100%. Return to our browser, we should now have a photograph there, so it makes that a little bit taller and they balance out a little bit more. Now with little additional CSS work, and the same basic row/column combination, you can make stuff look really nice. Here's an example of a site I completed recently. On the home page we have three columns, as we make the page narrower, when we get down to the smallest, everything stacks. So there's only a designation here for small and medium, and then the large follows the medium. Still take a look at a second page on this site, in the small screen, each of these packages are full-width, 12 of 12. They then jump to 6 of 12, and at large screen they stay at 6 of 12. Let's take a look at the Television. In this example large screens are 4-wide, medium is 2-wide, and small is 100%. Now we also have an example down here of a 3 of 12, 3 of 12, and 6 of 12, which in medium screen jumps to 6, 6, and a 12 beneath the 2. Now the important thing here is that this approach works on old browsers like Internet Explorer 10. Notice that this is stacking correctly, and when we shrink our browser, it stacks as a single column. The television one we also looked at also works well with everything presented correctly on all three different screen widths. Let's take a look at another page, which has examples of different row/column combinations. Here in the Course Overview page, this first row, which contains these three columns, each is set up as a different width. Notice that the Introduction is wider than the Overview, which is narrower than the Objectives. The Tasks and Watch are evenly set up as 6 of 12 and 6 of 12, and when I shrink it down, of course everything is now full-width. Wow, we've covered a lot of information in this module, starting with building our image sprites, how progressive enhancement works when you have multiple classes assigned to a division, some really cool SaaS, they built many lines of CSS from just a couple line of code, and finally, we built our example with sprites for the social icons, and we looked at several row-column combinations, and tested our work in Internet Explorer, which thankfully was successful. Now that we're done with the 12-column grid and image sprites, let's explore CSS shapes and masks.
Hello and welcome back. I'm excited to have you with me for this module. Since we're building a complete project we're going to cover using Font Awesome, CSS shapes, and clipping paths. First we will build our social icon set using an external font, and then try clipping paths for changing a square graphic into some other shape, and finally, explore the CSS shapes for a text wrapping.
Use Font Awesome for Social Icons
Let me introduce you to using a font for font icons. You're already familiar with using a custom font like Lato or Open Sans, for the text on your site, you can also use fonts for icons. Here are some of the advantages. Icons are vector-based, not pixel-based like the sprites we used in the last module. This means they're very smooth, especially on screens with a high resolution. Because they are a font you can use CSS to change the color, the background color, all without going back into Photoshop. The one drawback is that the download size is larger. The sprite we used in the last module was only 18 KB and contained 12 icons. When I load Font Awesome on Chrome, it loads the WOFF font, which is 75 KB, but it contains hundreds of possible icons. We will start by downloading a copy of the fonts from fontawesome.io. After unzipping the file you have these. We will use the css and the fonts folder. Copy the font-awesome.min.css to our start css folder, and then copy the entire fonts folder to the root of the start folder. It is important to maintain this folder relationship and the folder name so the font loads correctly. Now we need to add a link to our index file that points to the minified version of the style sheets. The style sheet now links to the font face needed for the web browser that you are using. If we look at Font Awesome Cheatsheet on their website and pick an icon like the address card, then inside an i or a span tag, we can assign it to classes. First the fa class followed by a space, and then the fa-address-card-o class, and it will display on our web page like this. By adding third class, such as fa-lg or fa-3x you can change the size of the icon, or we can make changes to our style sheet and change any property we want. Let's go ahead now and build our own. Please download the latest version of Font Awesome, open a clean copy of the start file and drag the minified CSS and the font folder to the start folder. Next open Brackets and make sure you have your CSS preprocessor running. Let's add a link to the minified CSS in the head of our index page, right below the link to our style sheet. Then from the snippets file in this unit, copy and paste the unordered list in the header, right above the h1. Now all we need to do is choose some icons. If we search the Cheatsheet, we can see several versions of Facebook, Twitter, YouTube, and Google+. To make them all consistent I'm going to use the -square version of each. Now let's enter a class of fa, followed by fa-facebook-square, and so on. Now when we pull up the page we can see blue icons with dots next to each one. Let's now work on the CSS. First we'll float the entire group of icons to the right side of the header, then we'll turn off the dots for each list item, and float each icon to the left so they line up horizontally. Then we'll tell all the anchors to increase the font size to 1.8rem, we'll put some space between each icon of .5rem, and then change the color to white. Finally, we will change the hover color to gold, which is the variable secondaryColor. When we look at it now it looks much, much better. The only change we'll make in the medium CSS is to increase the font size to 2.5rem. Now that our social icons are done, let's look at clipping paths.
Use Clip-path to Crop a Square Image
Clipping paths allow you to dynamically change the shape of a graphic in your CSS instead of using Photoshop. We will use clipping paths when we build our mobile music app later in the course. They're basically four different uses of clip-path, circle, which needs a single value of the radius, and an x and y point for the center. Ellipse, which needs an x and y for the radius, as well as an x and y for the center point. A polygon, which has x, y coordinates separated by commas, and there can be lots of them. These shapes can be really complex and very useful. And finally, the almost worthless inset, which simply crops an existing image. It's worthless because the amount of data needed to download the entire image is the same as the non-clipped version. So if you need a smaller image, just crop it in Photoshop and reduce the image size and download size at the same time. In order to get clip-path on the Safari browser we need to use a browser prefix, -webkit, in front of clip-path. The rest of the code is identical. For more complex shapes we can start with the Bennett Feely website, and modify or use what they provide. Then we just copy the code they provide. Let's jump back into our editor and try some of these out. There are several images in the demos for this unit that you can use as you follow along. The coordinates for a clip path work like this. The upper-left corner of the image is 0, 0. When using a value of 0 you do not need to specify a unit, like pixel or percent. The upper-right corner is 400, or 100% over, and 0 down. The bottom-left corner is 0 over and 200 pixels, or 100% down. Finally, the bottom-right corner is 400 pixels, or 100% over, and 200 pixels, or 100% down. We can apply clip-path to text, color division, and images. In our HTML we have created a paragraph with a class of ex1, and a division with a class of ex2, and a figure with an image and a class of ex3. In the CSS I use clip-path with circle for all three. I had to add height, width, and color to the division so it could be seen. Here's the end result on Chrome, cropping a text element is a waste of time because you can't read the text. But the orange circle could be useful, as could the image, if I had, say a face showing up instead of an elbow. So in the CSS I move the x-coordinate to 160px over and the y-coordinate to 55 down. And then I can see this, which could be useful. When using pixels for clip-path, the results are not responsive. In this example we will use percent for all the values and make them responsive. Our HTML will have three figures, with the same beach image. Each figure will have a different class name. The CSS will tell all the figures to be 50% of the browser width, and the images to be 100% of the figure width. This will make the images responsive. The first example will have a radius of 50% and have the circle centered in the image. Next we'll have a radius of 100%, but centered in the upper-left corner. Finally, we have a 50% radius that is slid over 50% and at the top. Now, can you figure out how these would have been created? Now let's expand our testing and look at the results on some other browsers. Opera seems to work well with clip-path, Firefox also supports it well. Safari is not supporting the standard yet, but do not despair, there is a solution. We duplicate each clip-path statement and then add -webkit- to the first one and we have our solution. Now I'm going to upload this to my sandbox and do some additional testing. Here's our page in Internet Explorer 11. And the results are not good. Here's the site on Microsoft Edge, and the results are the same. Now let's return to our editor and try some different shapes. Let's look at six more examples of shapes, using the music, island, and author images. The code for ellipse is really simple, we center everything at 50%. Now let's open up Clippy and get the code for a rhombus and paste it in ex2. Now let's get the code for a Right Chevron and paste it here in ex3. Next we grab the code for a star and paste it as ex4. Finally, we will go crazy with a heptagon and build our own custom shape with seven points. This will be our ex5. When we test these crazy shapes, we have success on all our standard browsers. When we look on our web page on Microsoft IE and Microsoft Edge, we see that only the author image worked. Remember that is has no clipping path, but rather was cropped in Photoshop and saved as a JPEG. So if you must have shapes in Explorer or Edge, you've got to use Photoshop. Unfortunately, Microsoft is not the only failure. The iPad 1 does not do clip-path either, using Safari or Chrome browsers. Now this is interesting, the iPhone 4 does not understand ellipse, but does understand polygon. As expected, the newer tablets and phones all work great. Now let's jump into CSS shapes used for text wrapping.
Use Shape-outside to Wrap Text
Now that we know how to crop an image using CSS, let's try wrapping text around these shapes. We're going to create several examples, each example will be wrapped in an article tag. Each example will have an h2 header, and each example will have an image inside a figure tag, followed by a paragraph of filler text. We will style the h2, the article, and float the figure in the small-default.scss file. This is what it looks like before we do our magic. Let's assign this first image a class of ex1, then we can return to the SCSS and add a clip-path to make it round. Don't forget the hack for Safari. Let's check to see what we have so far. Now here's the really cool part, it's called shape-outside, and it will take the same parameters as clip-path. Let's check it again and we can see a beautiful text wrapping. There's something you're seeing here that should really bother your sense of design. Yes, it's touching, so we need to add some margin to push the text away from the photograph. Let's add .5rem and then look at the results. Now that's pretty cool. Let's see how it responds in other browsers. Here's Safari, and it works out of the box. Hers's Firefox, but the text wrap fails. Here's Opera, and it works great. Let's modify this example by changing the radius to 100%, and relocating the center to 0, 0. We will paste this two more times and then look at the result. See how easy that was? Now let's try a polygon. We'll duplicate our article, change the image to island, and change the class to ex2. Now let's create a clipped corner using polygon. I'm going to copy and paste ex1 and modify it as ex2. We'll start it at 0, 0, and then move right to 100% and 0. Then down to the bottom-left corner where we have 0 and 100%, and we're done. Copy and paste this for webkit and shape-outside, and we're ready to test the results. Now let's try custom path using a graphic as our guide in the Clippy website. First we'll duplicate the article and change the class to ex3. We will also change the graphic to this letter carrier. Then we duplicate the CSS and change it to ex3. Now we need to make sure our letter carrier image is uploaded to a website. And I have it here on my sandbox test site. Then we open the Clippy website and load our graphic is as the background. Now we choose this tool and click dots around his arms and legs. Now we copy the polygon to shape-outside. We really don't need clip-path because our image is white on a white background, so I'll just remove this. Here is the end result. Now I'll do the same thing again, but this time as a text overlay. Start by duplicating the HTML and changing to ex4. And change the image to ceo.jpg. Also, duplicate the CSS and change the class. We'll load the CEO as the background image in Clippy. Notice that it does not fit properly. Let's go back and get the dimensions of the CEO graphic and then load them in here. This time we'll make it easy on ourselves by turning on the Show outside clip-path. Now use the custom polygon tool to create a mask. Copy just the polygon numbers this time. Paste them into the SCSS and view the final result. Notice the work we did in Photoshop to lighten the right side made a really nice blend here behind the text. Now that we have a few examples put together, let's upload it and look at the results on several devices and other browsers.
Once again, we see that neither clip-path nor shape-outside are supported in Internet Explorer 11 or the new Edge browser. However, the fallback position's really not that bad, we have a square image and nice wrapping. Windows users will never even know they're missing anything. Similarly, someone using an old iPad will not know they're missing anything. However, if you're using an old iPhone 4 you may wonder about the designer when you see this large, white gap. As with clip-path, all newer devices will properly show shape-outside. Wow, we have covered a lot of information in this module, starting with social icons using Font Awesome, CSS shapes, which worked great on most browsers, and finally, using shape-outside as a clipping path for text wrapping. Now that we're done with shapes and masks, let's work on flexbox.
Hello, and welcome back. I'm excited to have you with me for this flexbox module. We will begin by changing the navigation from floats to flexbox. Then we're going to implement a Sass mixin to create a reusable gradient. Next we will review the problems with columns and floats and look at a flexbox solution that works for text. Then we'll look at many of the flexbox parameters using a gallery of images, which I will provide. We will implement a CSS transition on the gallery images, finally, we will test our work on many browsers and devices. The flexbox model provides an efficient way to lay out a line and distribute space among elements within your document. So, what does that mean to you? It means that you can control the layout of children in a parent container. You can tell the children to line up left to right or right to left. You can tell them to line up top to bottom, or bottom to top. You can have them all fit on one line or wrapped to multiple lines. You can control the spacing around the images and text, and align the items, either top or bottom. In short you can do a whole lot of stuff that makes responsive design much easier. Let's get started by grabbing a copy of the start file from the demos for this unit.
Navigation Using Flexbox
If we open the index page in our browser we can see that the navigation items are broken. We're going to start by using flexbox to rebuild our navigation. Open the index file in your text editor. Notice that the menu items are list items contained in a standard unordered list. Therefore, the ul will become the parent and the list items will become the children. In the past we have displayed items as blocks, which means they take up the full width. Paragraphs and headings are examples of block layout. We have also displayed items as inline, which means that they flow of the HTML continues on the same line. Links and italics are examples of inline layout. Now we're introducing a third way to display, and that is flex. Please open the _small-default.scss file. On line 43 let's talk to the parent item, or unordered list, and tell it to display as a flex item. Let's see the result. This action alone is a great improvement. Remember that on small screens we want the menu to occupy the entire width, therefore we need each child item to be 25% of the entire width. Here on line 46 we will tell the list items, the children of the ul parent, to have a flex basis or preferred width of 25%. Now when we view the results in Chrome, Safari, Opera, and Firefox the result is exactly what we wanted. It even works on Explorer 11 and the new Edge Browser. If during your testing of Internet Explorer 10 your menu does not work, try adding these two IE-specific hacks. Display the unordered list as a -ms-flexbox, and the list items to use -ms-flex of 25%, and try it again. We want the tablet to be the same as the phone; however, on the desktop I want the menu items to float to the left. In our large.scss file we will tell the list item children to set their width to auto, which will remove the 25%. Basically this means fit to the content inside the menu item. Don't forget the ms hack. This works great in Chrome, as well as IE 11 and Edge. Now let's try a Sass mixin to spice up our navigation bar.
SASS Mixin for a Gradient
To create a mixin you start with @mixin, followed by a name you choose, followed by parentheses, and open and closing curlies. To column mixin you use the @include, and then reference its name in your Sass files. The best way for me to explain a mixin is to compare it to a function. A mixin can even accept variables as inputs and write code based on that input. We will put our mixin in the variables file and then call it from the _small-default file. remember that once a mixin is created you can call it from anywhere. Now let's pull up a website that creates a CSS gradient for us and turn it into a mixin. We're going to start with a two-color mixin. So I will remove these two center points, set the start color to black, and the end color to white. The Orientation we want is vertical down, so we're ready to copy the code. In the variables.scss file we will create our mixin by typing @mixin and then a name that we make up. I will use gradient then left and right parentheses, followed by left and right curly. Now we paste, add a code, between the two curly braces. We can remove the comments at the top and save our work. Now let's switch to the small-default file, and on line 41 we will call the mixin using @include and the name that we made up. When we test our work we can see a black and white gradient in the navigation bar. Now let's customize it by providing two hex colors separated by commas. In the variables file we will create two new incoming variables called startColor and endColor. Now we need to replace all the black hex values with the variable startColor, and then replace all the white hex values with the variable endColor. Now let's save and look at the result. While this is pretty ugly it does actually work. No let's send some colors that work with our design. let's send the secondary color as the startColor, and then we will darken it and modify the secondary color by 20%. That will be the end of our gradient. When we look at it the end result looks pretty nice. This is what the rendered CSS looks like. Now that our mixin is built we can reuse it over and over by calling it from, say, the footer, and sending two different colors. This is what it would look like with two shades of orange. It's not the flat look, but trust me, gradients will come back into popularity at some point.
Flexbox for Text
Earlier we looked at a 12-column grid, which uses floats to create columns. This works if the cells are the same height, as in this example. However, if the cells are different heights, as seen here on the table, cell seven slams into the taller cell five, and will not float to the left like it's supposed to. In the desktop version things get even worse, as cell two stops cell five, and cell five stops cell seven. We tried to fix this problem earlier using clear left on the nth child, but there is a much better way. Let's get back to our example and copy the first division with a class of container1 from the snippets file into the main of our index page. This is what the page looks like now. In the small SCSS file let's tell the parent division to display as flex. We will also include the Microsoft vendor hack. Now when we view it on our browser, all five items are presented horizontally, regardless of the browser width. Let's return to our SCCS file and tell the parent division to allow wrapping. Well that seems to have defeated all of our work, as they are now presented vertically again. This is because the children are all divisions, which are block elements, and the width is 100% by default. Now let's talk to the children divisions, or container1. And on the small screens we'll set the flexbasis to 100%, which is the default. Remember to add the Microsoft hack. Let's also add some padding to the children so they don't touch the edge of the screen. Here's what we now have for small screens. In the medium SCSS we'll talk to the children of container1 and set the flexbasis width to 50%. Because Internet Explorer adds padding to the outside and not the inside, we must reduce the Microsoft hack to 46% to account for the padding we added in the small-default.scss. Now when we look at it, notice that the Lost Cave article does not slam into the Bomb Fails article, as it would have with floats, but instead moves gracefully to the left where it's supposed to be. Let's copy this line from the medium SCSS, and paste it into the large SCSS. We'll change this to 33.333% and 29.333% for IE 10 hack. The end result is a proper display of text articles regardless of the screen width. When we test our work on the Internet Explorer and Edge it works great with one minor problem on IE. Notice that the second row stretches the last two articles to 50% instead of 33%. Well that we can live with.
Flexbox for an Image Gallery
In the demos for this unit there are 16 images that are landscape, portrait, and square. Each one has a letter embossed in the corner so we can track the presentation order. We will use the power flexbox to present these in several different ways. Let's start by copying all these images from the demos to the images in the start folder. Now let's open the snippets file and copy the division with a class of container2. We'll paste it above container1 so that it shows at the top of our page. When we look at our page there are 16 photos stacked vertically. Now let's open this _small-default.scss file. Let's type to the parent and set the display to flex. When we look at the results we see 16 images presented horizontally across the screen. Let's go back and add wrapping. As we adjust the screen size we see the number of columns changing, but the images are not scaling. They are all being shown at their default size. We'll change this later. Setting the flex-direction changes nothing, because it is the default value. Changing it to row-reverse changes the presentation from right to left, but the top row is still showing the first three images, A, B, and C. Now let's switch it to column, which shows them in a single column again. If we add a limit to the division height of say, 1600 pixels, then we can see multiple columns. If we use column-reverse then we can see that they start at the bottom. Not sure how this would be useful, but you may find a way to use it someday. Let's put flex-direction back to row, and remove the height restriction. When you justify lines of text using a word processor there are four kinds of alignment you can choose from. Left alignment is the most common, center alignment is also used a lot, right alignment is the third, and finally there is justify, where both sides of the text are even. Flexbox has the same four alignments types, plus a couple of additional ones. The default value for justify content is flex-start, which leaves everything lined up against the left edge. If we change it to flex-end then we basically have right alignment. Changing it to center puts extra space at both sides. Using space-between keeps the edges even and divides the space between the images. There is also space-around and space-evenly, which you can try on your own. Now I'm going to move on to align-items, because that one is really useful. Let's add align-items and set the value to the default of flex-start. This one's a little bit hard to see with images, so I'm going to start by adding a background-color to the figure tags, which are the children of container2. The end result is that the rows are all aligned at the top, no big surprise there. Similarly, if we use flex-end the images are aligned at the bottom. This would have been very useful for a couple of projects in my past. Setting align-items to center is also no surprise, as you can see the centers are lined up. The last one is stretch, which forces the figure tag to expand so they are all the same height. While this is not very useful with images, let's try it on the text items at the bottom of the page. We will add align-items: stretch to container1 and set the background color and the border on the children of conainter1. The end result looks like this, which is difficult without flexbox. Let's put align-items for the photos back to flex-end and remove the background-color. Right now the number of images showing is based on the original size of the images. In our case, these images are no larger than 300 pixels in either direction. We're now going to make them display in two columns on a small screen by setting the flex-basis to 50%. We'll add some padding around the images so they don't touch each other. Finally, we'll tell the image inside the figure to resize to 100% of the figure width. Here's the result on a phone. On medium screens we'll display them at one-third so we get three across. This is the result on a tablet. On large screens we'll display them at one-fourth, so we get four across. This is the results on a desktop. Now just for fun, let's throw in a CSS transition on these images. Back in the _small-default.scss file, let's add a hover pseudo class. We'll add a transform scale of 105%, which is not much, but enough to make the images look alive. Notice how they look at little jumpy when we hover over each one. Let's return to our SCSS and add a transform to the figure at three-tenths of a second, using ease-in-out. Now we have this nice subtle response on image hover. There are still some more features of flexbox, but we'll cover them in the final module of this course where we design our music player app.
Let's begin our testing with Safari, Firefox, and Opera, which all recognize flexbox. Of course we already know that Chrome works. Now let's look at flexbox with Microsoft's newest Edge browser, where the results are also great. We even had success with Internet Explorer 10 and 11. Now let's back up in time to 2011, where we have Safari, Chrome, and Firefox on an iPad 2 with complete success with flexbox. If we back up one more year to 2010 we can see that flexbox is not working; however, the fallback position, where everything is full-width, is still manageable for anyone still hanging on to a device that old. As you can see, flexbox is pretty cool. In this module we have converted our navigation to flexbox, and then used Sass mixins to build a reusable gradient. We looked at the problems of using floats for grids, and then how flexbox can help us out with text, and a gallery of images. We tossed in a CSS transition just to make our page zing a little, and then tested our page on several different browsers and devices. Now if you like the power of flexbox you're going to love CSS grids, which we will do next.
Overview of CSS Grid
Hello, this is Paul Cheney, let's jump in and explore CSS grid; it's great for responsive layouts. First we'll contrast the difference between flexbox and grids. Next we'll build a page of text with grids, then we'll try an image gallery, and then do a complete page layout using only CSS grids. Finally, we'll test our work in multiple browsers and mobile devices. So what is CSS grid and how does it compare to flexbox. As we saw in the previous module, flexbox is great for laying out items in a single dimension, in a row or a column. Grid is for a layout of items in a two-dimensions, rows and columns. If you want to let your content control the way it's displayed, on a row-by-row or a column-by-column basis, use flexbox. If you want to define a grid and either allow items to be auto-placed into the cells defined by that grid, or control their positioning using CSS or grid templates, that's grid. In this module, we will build three layouts using CSS grids. The first one is just text. The second one will be a new site with the top seven storied represented as images. you can see how the phone, tablet, and desktop are all presented in different ways. In this example we will only use grids on the content of the main tag. In the third example we lay out an entire site, including these six items and position them differently in each of our three layouts. Grab a copy of the start file from the demos for this module. open it in your text editor and let's get started.
Text Blocks in CSS Grid
Let's open the snippets file for this unit. Copy and paste the code for a division with a class of parent to the main tag of your HTML document just below the Breaking News headline. Now open your _small-default partial Sass file. Let's tell the parent item to display itself as a grid. Make sure that your CSS preprocessor is running. If we view the HTML page there is no visible difference. Now let's create some columns by adding grid-template-columns. Let's start with 250 pixels and auto. This will create two columns. The left column will always be 250-pixels wide regardless of the browser width. The second column will fill the remaining space. Notice that as we change the page width, the first column is fixed and never changes, the second column in filling the remaining space. With grids we can use a new unit of measurement called a fraction, written as fr. Fractions are great because we can just enter various fractions and the browser does all the math for us. For example, if we had the column set to 1fr and 2fr, the fractions would be added up, in this case 3. It would then divide 100% by 3, giving us 33%. Since the first column is 1 fraction it would be given 33.3%. Since the second column is two fractions it would be twice as wide, or 66.6%. Since we're calculating fractions of the page width, this works on any display width. Now let's divide the page into three fractions, with the middle fraction being twice as large as the other two. Let's see the result. This is so easy. We don't have to worry about the blog articles being different heights, it just works. Now let's try a standard and multiple column layout, by setting the small screens to a single column or fraction, we'll set the medium screens to display two even columns or fractions. Finally we'll go to the large screens and show four even columns. You have got to be so excited right now seeing how much easier this is than the old way of creating rows, and columns, and floats. But please don't leave yet because the best is still ahead. Let's open the large and _medium.scss and comment out the grid column statement. Back to the small SCSS let's create two even rows with one fraction and one fraction. Now let's select the first article using nth-child with a 1. Then we'll set the grid-column to start at column 1 and span 2 columns. Let's also set the background color to orange so that we can see it. Here's the results in a browser. Let's change the medium SCS and create three fractional columns. We'll then at the first article start at column 2 and span 2 columns. Notice in the results that the first cell has been left empty. Let's go back and have it start at column 1 and span 1. Now let's set the grid-row to start at 1 and span down 2. Here's the results. Now let's jump to the large SCSS file and create four even columns. We'll change the first child to display two-columns wide and two-rows high. This is what we have. Let's go another step and have the second article change its background-color and have it start at 3 and span 2 columns. Here's the result. Now I can feel your sense of design is screaming in pain because all these rows and columns are touching each other. Let's return to the _small-default and assign a light-gray color to the background of all the children items. Here's what we have. Now let's add a column gap of 2%, and a row gap of .5rem. Remember, in responsive design we use percent for side measurements and fixed values like pixels, or ems or rems for top and bottom. Notice how the articles are now spaced apart. Let's remove the background colors and take another look. Here's the results on a small screen. Here is the medium screen with a taller leading article. Here's the largest screen with a large leading article and a wide second article, and all this was done entirely with just a few lines of SCSS.
Image Gallery in CSS Grid
Now let's move on to design different layouts using CSS grids and images. Building this one should be a lot of fun. Instead of using nth-child to reference the children, we're going to use class names and then assign them a location using CSS. We're also going to test our work and discover that CSS grids don't work very well on Explorer, or even Edge, without some vendor prefixes. We'll then modify our SCSS so it works everywhere. Let's get a clean copy of the start file from the demos for this module. Copy the seven photos to the images folder on the start folder. Open your text editor and CSS processor and let's get started. Open the snippets from this module and copy the second block of code, which is seven divisions with a class of teaser. Paste it in the index page just below the Breaking News heading. When we preview the page we get a stack of images with text to the right of each one. Let's start by moving the text over the image and sizing it properly. Open the _small-default file and around line 103 let's tell the divisions with a class of teaser to position themselves as relative. Next we'll talk to the span inside each division. position each one as absolute and display as a block. Now we can set the bottom to 0 so the text sits at the bottom of the photo. This is what it looks like. Now let's set the background color to rgba block at 30% transparent. As you can see, the block color is only as large as the text. So let's set the width to 100% so it extends all the way across the screen, like this. Finally we add some padding around the text, change the color to white, and increase the font size to 1.5rem for small screens. Now it looks like this. With the labels styled we are ready for the grids. We want the division images to scale with the grid cells, so let's tell them to display as blocks and set the width to 100%. Now they're scaling to the full width of the main tag. Let's scroll up to the main tag, which is the parent, and tell it to display as a grid. For the small screens we want to set the grid-template columns to two equal fractions. We will also provide some space between cells using grid-column-gap at 10 pixels, and grid-row-gap at 10 pixels. When we look at the results we see that everything is now fitting inside one of the grid cells including the h1 Breaking News text. I really don't want it to have a page name, so let's just remove it from the index file. Now it looks like this. Here's where the fun begins. Our design calls for the leading image to be full-width on the small screen, so let's go into our index page and add a class to the first item of lead. Now let's open the _small-default file, and around line 125 let's reference the division with a class of lead and assign it to the grid-row 1 and grid-column 1, with a span of 2, that should do it. Here's the result. The next two articles are also full=-width on small screens. So let's go back to the index file and add a class of secondTop and secondBot. To make things faster let's copy the division.lead and paste it two more times. Change the class to secondTop and secondBot. Change the grid-row to 2 for the first 1 and 3 for the second 1. The last four articles flow automatically into the remaining spots on the grid and we're done with small screens. For medium screens we display the lead article in the first column, but double the height. The second-level articles are to the right as one cell in height. Please copy the code for these three articles from this small file. Open the _medium.scss file and paste in. In the lead we add a span of 2 to the row and remove it from the column. Remove the span of 2 from both of the others. The second top will change to row 1 and column 2. The second bottom will change to row 2 and column 2. Do you see this gray border along the bottom? We will remove it by adding align-self: start to the top item, and align-self end to the bottom one. This will keep everything aligned to the lead image. We still have one more to go. Let's copy the CSS for lead and second articles. Paste it into the _large.scss file where we'll get to it in a minute. But first we need to change the grid layout to four equal fractions using grid-template-columns. We don't need the align-self here, so we can remove these two statements. The lead article should now start at row 1 and span 2 rows. It should also start at column 1 and span 2 columns. This action caused a bit of a mess in our browser. The secondTop needs to stay at row 1, but start at column 3 and span 2. The second bottom stays at row 2 and starts at column 3 and spans 2 as well. Here are our awesome results on a large screen. Notice in Chrome how nicely all the images line up and the gaps between them are so even. Safari also look great, as does Firefox, and Opera. Unfortunately, at this time Explorer and Edge are a disaster with CSS grid, but not to worry, we can hack our code with browser prefixes to fix this problem.
Microsoft Prefixes for CSS Grid
Let's return to our _small-default file and add display -ms-grid. We also need to use a prefix for the number of grid columns. Down in the code for the lead class we need to set the grid-row, grid-column, and column-span as three separate statements, with the ms prefix. It's the same information as above, but separated out. Repeat this action for the secondTop and secondBot. Now when we look at the results we can see the lead and second articles are in the right place. However, the remaining four are all stacked on top of each other in the first grid cell. The problem is that the remaining items do not automatically flow into additional cells, we have to manually place each one. Return to the HTML file and add a class to the remaining four articles of ie1 through ie4. Now in the small SCSS file we will position all four to the exact cell they are to occupy, ie1 goes in row 4, column 1. Ie2 goes in row 4, but column 2, ie3 jumps down to row 5, and column 1, and ie4 stays in row 5, but in column 2. Let's try this again in a Microsoft browser. Do you know what's missing here? Yes, there is no space between the images, it turns out that Microsoft does not support the column and row gaps, even with a prefix. So this would just have to be the fallback position, it's really not that bad. We still need to fix the _medium.scss by setting the four ms prefix values for the lead and secondary articles. In the large file we need to use the ms prefix to set the number of columns to four equal fractions. We also have to replace all the information for the lead and secondary articles. The final four with classes of ie1 through ie4 need to be placed in row 3 columns 1 through 4. Now let's test our work in IE 10 and 11, small screens, medium screens, and large screens. And it all seems to work, other than the gap. Here is Edge with the narrow screen, medium screen, and large screen. Now let's try building an entire page with CSS grids.
Complete Page Layout Using CSS Grid
So far we have referenced grid areas by their row number and column number. However, we also have the ability to name an area like navigation and then just assign something to display in the navigation area. This is really powerful if you think about it. By the end of this lesson you will have built a small screen with a navigation button and social icons at the top. The navigation links will be at the bottom. On the tablet we are going to place the navigation links at the side of the main content. And on large screens we'll move the navigation just below the header. All of these changes will be made using only CSS grids, no floats or absolute positioning. This is how it works. First you define a grid using template-columns and template-rows, which in this case gives you a two-column and four-row grid. Next you give names to all the areas. Any areas that match are automatically combined into a single cell in the grid, and they take the names assigned in the CSS. Of course we will not be using animal names, but I want you to understand that these names are made up by you. Once the grid is created you simply use CSS to assign them a location, the order in the HTML does not matter. I had to remove all the floats from the template and add Font Awesome social icons so, I need you to get a copy of the start 2 folder from the demos for this unit. This is what the file currently looks like small, medium, and large screens. When we're all done we want our small screen to look like this, so we're going to slice it up into rows and columns. Because the hamburger icon is on the left and the social icons are on the right, we need to split our page into two columns. We will then slice it four more times to create five distinct areas, the first one with the hamburger and social icons will be a fixed-height of 3rem. The second one with the World News and slogan will be auto, so it resizes to the height of the h1 and h2 tags. The third area is the main content, and it will change size a lot, so it needs to be auto. The fourth area is the footer. We'll set it a height of 3rem. The last area is the navigation links. We need to be able to set them automatically so they adjust to the size of the phone. As you can see, we have a lot of work to do, so let's get started. Open your text editor and make sure your CSS preprocessor is running. Notice on line 20, just inside the body tag, I have created a division with an id of wrapper. This will function as the parent item. This division ends just above the body tag and contains six children, the header, social icons, hamburger icon, main navigation, content, and footer. In the small file, let's talk to the div.wrapper on about line 14. Add a display of grid, which by itself will do nothing, until we add grid-template-columns with two equal fractions and a grid-template-rows with five rows we just talked about. As you can see, this creates a grid that is two-columns wide with each child of the wrapper taking the next available cell, that's not exactly what we want. Let's give each of these areas names, and while we're doing it, we will combine some of them together. The first one we'll name hamburger. The one to the right we will name social. Then we'll combine these two and name them header. We'll combine these and name them main. We'll combine these and name them footer, and combine these and name them links. We do this with grid-template-areas, and when we're done it looks like this. So there are two names in each of the five rows. When we look at the result it's still a mess, but now the fun begins. Let's tell the hamburger icon to display in the hamburger space, and center itself top to bottom. This is the result. Notice that the World News heading is in the social area. Let's assign the social icons to the top-right social area, and then justify-self as end. Remember this is like right alignment in a word processor. We will also center them top to bottom. This is what it looks like. Now we'll assign the company name and slogan to the full-width header area. Notice that it is now full width. Let's jump down to main and assign it to main. Notice that the order in the HTML has nothing to do with the order in which we are placing them in the grid. Now when we view the page the main is correct. Now let's assign the footer to the footer, and also center it top to bottom using justify-self. While we're back here let's also assign the nav area to the links grid area. Now let's look at the site and phone emulation and try out the hamburger icon. Notice how the links fill the screen completely. This is because we are setting it to a height of 100vh. So no matter how big or small your phone is, the links will always exactly fill the screen. Now we are ready for the medium screen layout. It's pretty clear that we need to slice this into three rows, but what is not so clear is that we need three columns. The links at the left are a fixed width, but the header is larger than the links, and so we must slice it again from top to bottom. We'll then create the following combined areas. Notice that the hamburger is missing. We simply hid it from medium screens. Let's try this out in our editor. Open the medium file and set the grid-template-rows to 5rem for the top row, auto for the middle row content, and 3rem for the bottom row. Next we create the grid-template-columns with the first one at 10rem, this is for the navigation, auto for the middle, and 12 for the social icons at the right. Now all that's left is to name these areas as follows, header and header combined, then social, links, then main and main combined, three footers combined. It looks great in our emulated tablet, but we have this hamburger stuck at the bottom of the screen. Let's return to the medium file and tell the hamburger to display as none. Now when we look at it we have complete success. Since we already assigned items in our HTML to grid names in the small file, all we had to do here was build the new grid and everything went into the proper location. My guess is that you can look at our desktop layout and know exactly what kind of grid we need to make. We will divide it into two columns and four rows. Without wasting any more time let's get to the code and try it in our large file. The grid-template-rows will be 5rem for the header and social, auto for the navigation links, auto for the content, and 3rem for the footer. Columns will be auto and 12rem for the right side. The template areas are header and social, links combined with links, main combined with main, footer combined with footer. When we view it we get this, which is close, but the navigation links are still vertical. Let's go back to our code and create a grid inside a grid. We will tell the unordered list, which is the parent of the list items to become a grid. Then we create template columns of 9rem for each menu item, and auto for the extra space at the right. This is the end result. Let's scale this page back and forth, and notice how smoothly these grids work.
Here is the end result in Safari, here is the end result in Firefox, here's our work in an Opera browser. As we've already determined, Microsoft browsers are having trouble with grids, but that's about to end with Edge. By now Microsoft will have released version 16 of their Edge browser, and naming grid areas will work beautifully. My iPod Touch, with a screen width of 320 CSS pixels works great in both landscape and portrait orientation. And my iPhone 6 from 2014 also works. Even my iPad from 2012 works with grid areas. My daughter's Samsung phone also works great. So that wraps up our exploration of CSS grids. We started out by contrasting the difference between flexbox and grids. Then we built a page of new stories using CSS grids. Next we built an image gallery using grids. Finally, we capped everything off using a full-page layout with just grids. Then we looked at modern browsers and the mobile devices I have in my possession. With all this knowledge under your belt we are ready to design a music player using everything we have learned so far.
Music Player Project
Introduction to Player App Interface
Congratulations, you made it to the end. In this module we are going to combine everything we've learned together to build a music player for mobile devices. First, we will design and build the template, then we're going to design and build the Album page, and then the Artist page. And finally, a Player page, which is linked from the Album and Artist page. In the demos folder I have two Photoshop files with images that are ready to export using Adobe Photoshop generate assets. We learned about that in depth in the second course in this series. In case you don't have Photoshop I have provide the assets as well. I also have a start HTML folder, and I have included a Photoshop file for generating four images that are sized correctly for Safari's add-to-home feature, which we'll demonstrate later.
Building the Template
Building the Album Page
Now let's build out the Album page using responsive images, which we learned about in the second course in this series. We will lay out the album using figure and figcaption. The figures will live in a grid column defined using two fractions for small screens and four fractions for wider screens. To support responsive images in the Album view we've created two different versions of eight images. The small ones are 200-pixels square and the larger ones are 400-pixels square. If you look at the layers palette of the player albums PSD file, you will see that each layer has two names, separated by a comma. We covered creating responsive images using Photoshop in the second course in this series. The demos folder for this unit contains a Player_album-assets folder with all 16 images. Please copy these images to the images folder of the start folder. Our design calls for two columns on small screens and four columns on medium screens. We are not developing for large screens so we need to make some changes to the styles.scss file. Let's open the styles.scss file and remove the reference to large. Now let's change the min-width for medium to 29rem's, or 464 pixels, which is a safe breakpoint for phones between the landscape and portrait orientation. We're going to build three pages for the player application in this module. We do not want the CSS from one layout to cross over into the CSS for other layouts, so we will give the main tag a different class for each different page. On the Album page, the main will have a class of album, on the Artist page the main will have a class of artist, and of course on the Player page the main tag will have a class of player. Let's start by adding a class= album to the main tag. Now we'll add an opening and closing figure tag to hold the image and the caption. Since we want these images to be clickable, to play the song, we'll next add an anchor with an href pointing to the Player page, which we'll build later. Below the closing anchor tag add a figcaption that says On the Beach. Now we're ready for the responsive images. First we'll add an image tag with the default source set to images beach200.jpg, this is for _____ browsers. Now we'll use a srcset based on device pixel density, or dots of light, as we covered in an earlier course. Inside the quotes, type a path to the beach200 image and tag it with a 1x for computer monitors and other 1x displays. Then type a comma and the path to the beach400 image, and tag it for Retina Displays that are 2x or higher. This image will show on any modern phone. Now let's open the _small-default file and create a section for main.album. First we set it up as a grid, and we add two even fractions for the columns. We'll let the number of rows be automatic. Now we need to create a nested figure and add some padding. We'll use .7rem for the top and bottom and 2vw with the sides. We'll tell the image in the figure to display at 100% of the figure. We can then style the caption by centering the text and adding some padding around the edges. Now open the medium file and create a main.album rule. Change the grid template columns here to four equal fractions, and that should do it. Now let's test our page with Chrome tools up and the screen size set at 320 x 500. Notice in the Network tab that the beach200 image is loading correctly. Now let's change our emulation to a phone and reload the page. Now we can see that the larger beach400 image is loading correctly. This is because it's simulated Retina Display that's 2x or higher. With one of these images in place and working correctly we can simply copy and paste the other seven figures and change the image reference, or you can open the snippets file and copy the code for the remaining seven images and paste it below the beach image. Here's what we now have on a phone in portrait mode. Here's the phone in landscape mode. We can also look at it in tablet portrait mode or tablet landscape mode. Now let's tackle the Artist page.
Building the Artist Page
The Artist page will be really simple. We will lay out the page using grids, we use a clipping path to make the square images round, and we're going to use nth-child to position the name of the artist. The images we'll be using are 160-pixels square, and will be displayed in an 80-pixel space, which is ideal for mobile retina screens of 2x or higher. Before we start coding make sure you've copied the six player artist images to the start folder. First we need to duplicate the index page and rename it artist.html. Next we need to delete everything inside the main tag. Now we need to change the class from album to artist. Let's create an opening and closing section tag for each one of the artists. Inside the section create a division with an anchor to the player.html file, which we will need to build. Inside the link add an image with the source pointing to the andrea160 image. Below that add a second open and close division. Put Andrea Reys as the name. This is what it looks like so far in our phone simulator. Since it's working correctly let's do the remaining five artists. The code you need is in the snippets file in the demos folder for this module. Paste it here right below this section. Now this is what it looks like in our phone. Now let's jump into the CSS. Remember that our CSS preprocessor will strip out all comments and empty lines, so we can put all the extra stuff in here we want to help us keep our file organized. Let's create the main.artist section with an ending comment. We will display all the children of the main in a grid. In the portrait mode, we have one column, and we'll set up the rows as automatic. Now let's talk to the children of main, which will be the sections. Once again we will use the nesting feature of Sass and add a section with an open and closing curly. Please put a comment by the closing curly brace. Let's display each section as a grid inside the main artist grid. The first grid column will be 80-pixels wide for the image, and the second will be auto to fill the rest of the space. Let's add some margin around each section, so the images do not touch each other or the edge of the screen. Now you can see the additional space separating the images. Now we're going to do a double-nested for the image inside the section, which is inside the main. Add a width of 100%. This will force the image to fit inside the 80-pixel wide column. Next, let's make the square image round by using clip-path and a circle of 40 pixels at the center. We also need to do a webkit version of clip-path for Safari. This is what it now looks like on our phone. Notice that the name automatically moves into the second cell in our grid. Now let's do a double nest for the artist name using nth-child and 2. We will use align-self to center the name top to bottom. And add padding at the lab so the name does not touch the photograph. Here's our work on a phone in portrait mode. Now let's change to landscape mode, and we have a little bit more work to do. In the medium file we need to talk to the main.artist and simply change the number of columns to two equal fractions and save our work. Here's the result in our phone. Can you see two additional changes we still need to make? Yes, the title and the active menu item. Back in the Artist page we'll change the header to artist, and in the navigation we'll move the class= active to the second division. Here is the final result for the Artist page on a phone in portrait orientation. Here's the final result in phone landscape. And here's the result in a tablet, for a portrait, as well as landscape modes. Before we move on there's one more tweak we need to make for the Album, Artist, and future Player pages. You may have noticed that when we are in phone view the page will not scroll down to show the last album or the last artist. This is because they are hiding behind the navigation links. Open the small file and add main padding-bottom of 2.75rem, this will affect all three pages. This is what it looks like now in our phone emulation mode.
Building the Player Page
Now we're ready to tackle the most complex page in this module, the Player page. We will be using CSS grids with named grid areas. Responsive images with source set and width, a form input of type range to simulate the progress bar and volume level, border radius to round the image corners, and finally Font Awesome for the player controls. The Chrome Emulator does not work well with the input progress bar, in fact, it completely ignores it. This means that our testing will need to be done by resizing the browser window, or viewing the page from a real web server on mobile devices. In the demos for this unit there is a howl.psd file, which is set up to export four different-sized images when you use generate image asset. The howl assets folder has the optimized images directly from Photoshop. In the labeled folder I've added a red number to indicate the image width. These images will be used for testing, and once the project is complete we can replace them with the unmarked images. Please start by moving the images from the demo's folder to the images folder of the start folder. Next, duplicate the artist.html file and rename it player.html. Open your text editor and change the header h1 to Player. Select and delete all the sections inside the main tag. Remove class= active from the second link. Change the class from main to player. We're going to lay out everything in the Player page from top to bottom, just so we can maintain our sanity. You could put them in any order in the HTML and the page would still work using CSS grids and named areas. Every element will be a separate division, each division will have a class so we can place it into any grid cell. Inside each division we'll place one of the many elements in our page. Remember that our media query breakpoint between small and large screens is 29rems. Therefore, when we set up the sizes, inside our image tag, we need the breakpoint to be the same value. If the minimum width is greater than 29rem then we will display the image on the left half of the screen. Otherwise, the image will occupy the full width of the screen. Remember that the browser calculates which image to use based on the screen width, the pixel density, and the display width. So if I was using my iPod Touch with a 568-wide screen and a 2x pixel density, and the image was half the screen width, then I would need an image that was at least 568 wide. So the 650 image would be selected. If I was viewing the page in portrait mode on my iPhone 6 then the screen width would be 375-pixles wide, with a pixel density of 2x being displayed at 100%, then the image would need to be at least 750 wide. So, the 750-wide image would be chosen. I cover this is great detail in the second course in this series. Our first division will have a class of photo. The img src will point to the howl650 image, in case you have a _____ browser. The sizes and srcset we just covered in detail, and it should look like this. Actually, I have a copy of all this code in the snippets file for this demo, so let's save ourselves a lot of time and headache, and just copy and paste all 11 divisions into the main tag, and we'll talk about each one. We have three divisions used to track the time elapsed, the time remaining, and a visual indicator to show progress. For the horizontal bar we are using a form input of type range. This may or not be what is used by the programmers, but it makes a nice visual indicator for this module. The next division contains the song title and the band name. The next three division are for controlling the music, and we are using Font Awesome for these icons. We have the previous icon, the play/pause icon, and the next song icon. The volume controls are almost identical to the audio controls, with Font Awesome icons, but with a range input. Here's what the page looks like in a skinny browser. For the portrait version we are going to create three columns using 50px auto and 50px. The grid rows will be auto, but as you can see there's going to be a lot of them. We will create template areas like this, photo combined, time combined, startTime and empty cell and endTime, title combined, previous, play, next, volume up, volume slider, and volume down. Let's jump back into Brackets into the small file and create a new section for main with a class of player. Set it up as a grid, with the grid columns at 50, auto, and 50. Set the rows to automatic. Now create your template areas like this. Finally, we need to add some margins to the top of the player, so the image sits down a little bit. When we view our page in a browser, we can see the margin at the top and we still have a lot of work to do. The next project is to assign all 11 divisions to their proper named place in the grid. Once again, I have provided this bit of code for you in the snippets file for this module. Please copy this block of CSS, then paste it in the small file below the CSS grid template areas. Let's look at our page and we can see that all of the items are now in their proper place. But we still have a lot of work to do. Below the div.photo let's talk to the image. Set the width to 84% and add a margin of 0 at the top, 0 at the right, .5rem at the bottom, and 8% at the left. An 84%-wide image plus 8% at the left automatically leaves us 8% at the right. As you can see, this centers the image. Now let's round the corners using border radius and 20px. That looks great. Now let's work on the time indicator. Let's add justify-self center, which is the same as align center in a word processor and make the width 84%. If we use the Chrome Inspect tools we can see that the division for time is centered and 84% wide. Now we need to make the range slider 100% wide. And as you can see it's looking really good. Notice that the start time is touching the left edge. Let's go back to the SCSS and tell the start time to text-align right instead. And there we have a nice balance. The title and the band now need some work. We will have both spans change to display themselves as blocks. (Working) Then we talk to the first span using nth-child of 1, and set the font size and padding. (Working) Now let's talk to the second span and set the font size and padding as well. This is the result, and it looks so much better. As we move on we can see the Player controls are too small and they need to be aligned differently. In the CSS let's tell the previous button to justify-self: end, which is like right align. And we'll increase the font size. For the Play button we'll copy and paste and change the justification to center. For the next button we'll copy and paste again, and change the justification to start, which by the way is the default, we'll leave the font size alone. When we look at it in a browser it looks much better, but we need some space below, so let's add padding-bottom to the play button of 1rem. This looks better, so let's work in the volume section. Let's move both of the speaker icons to the center using justify-self. That looks better, but we need to work on the range input. In the SCSS let's simply tell the input to be 100% of its container. And it looks marvelous in our browser. In this view we're going to combine rows and columns. First we divide the space into four columns using 50%, 50px auto, and 50px. Again, we let the rows be automatic. So the first word in all of them is photo. This gives us a combined column. Then we have photo, startTime, time, and endTime. Then photo, and title combined. Then photo and previous, play, and next. Finally, photo, down, volume, and up. Now let's go back to the text editor and type in all the code we just reviewed. This is what it looks like when we're done. Everything fits into the proper grid cell based on named areas, and we're done. Let's up load this to our Sandbox test folder on our server, and try it out with some real devices.
Here's the results on my smallest mobile device, and the 650 image is being displayed. Here it is on my iPhone 6 and the 750 responsive image is selected. If we bump up to the larger iPhone 6 Plus with a 3x screen, we get the largest of our responsive images showing. Here's our work on an Android phone. Even though this is not designed for an iPad it still works. Before we deliver this work to our programmer we need to swap out the branded images with the nice photos, and then go get a dozen doughnuts to celebrate. While you're munching on one of those doughnuts let's review everything we've covered in this course. First we built the template header and footer using flexbox, and then built the Album page using grids. Next we built the Artist page using grids and clip-path. Finally we built the Player page using grid and named areas and responsive images. Building this course was a lot of fun and I hope you've enjoyed learning about the new CSS layout options that are now at our disposal.
Paul Cheney is a professor of Web Design and Development at Utah Valley University, where he teaches Responsive Design. He also owns his own web design company, which allows him to keep current in...
Released13 Nov 2017