Learning to be Responsive


I'm doing my first slice from photoshop to responsive web design theme for concrete5.  I had taken several html/css files using the skeleton css framework and turned them into themes, but I haven't done one without a framework and I haven't done the slicing myself.  Here's some of the stuff I've found out so far.

I haven't done a whole lot of work or research into responsive designs before.  I know the basics, using media queries for different widths to adjust your content so that it displays properly on different devices and screens.  It's pretty popular in web design right now, it seems like most of the designs being released to the concrete5 marketplace these days are responsive.  We have had one designer who has sent us several themes so far using the skeleton css framework, as finished html / css which I then convert into concrete5 themes.  So I had some experience with how to make html flex for different sizes, but only with a framework.

This time around, that designer actually referred us a different designer who we've never worked with before.  He sent us photoshop files, not finished html, so the starting point was a lot different.  I started going through the designs, and there were a ton of different views that he supplied, desktop, tablet portrait and phone views.  But it wasn't really set up to use a grid system across those views, and the several different page types all had different custom widths for columns and content and footers, font sizes, line-heights, etc.  So much more to think about than just setting up the proper classes on divs and trusting the framework to adjust it.

I started doing research on programing without a framework for responsive designs, and one of the first things I really started seeing was that there's a difference between an adaptive and a responsive design.  I thought that these two were pretty much interchangeable terms, but it turns out that there's a lot of difference.

For starters, remove yourself from the device based breakpoints mindset. And get into the design based breakpoints mindset. Make adjustments where the design dictates. Pull your browser window out and see when the design starts to break – that’s your first breakpoint. Use a media query, fix it up and repeat the process. Simple!

That was a pretty big revelation, especially looking at this design.  There were a lot of different points where things needed to adjust, and they weren't just at the points where the media width changed.  I tried finding more information about what common media widths were, and it seemed that there were dozens if not hundreds of different sizes.  Plus there was the possibility of changing your browser window width on any of these different screens, too.  So much more to think about than what a css framework gives me, at least any of the frameworks that I'd read about.  So I started out trying to program it as device agnostic.  That was good, but I was still using media queries in pixels.

To start figuring out how to design for all these different sizes, I needed to find a way to measure what the size of my window was.  There are a few different tools that you can use to resize the design of a site in your web browser to different platforms.  The one that I'd used before was responsive.is - this lets you click a button and scale to tablet or phone, it seems like all you need right? The problem is, not all tablets have the same sizing, and neither do phones.  And the widths are quickly changing as new technology comes out every few months.  The other problem with it is that it won't let you preview a site that you've defined with a localhost / hosts file override.  That's how I do most of my development, so having to push changes to a live site in order to test the design was really not workable.

So I was looking for a different solution, and I found a tool called Responsivator on github.  This was much better, it would let you do a localhost override, and you could set exactly the sizes that you wanted to display.  But it was still pretty limited.  You had to say exactly what the pixel dimensions were, so if you needed to do something like reduce some padding on navigation by 3 pixels between a normal device split, you couldn't really preview.  My thought was this - why not make it into something where you can drag the iframe and update a display with pixel widths?  Then you wouldn't need to enter a bunch of different widths, reload the page, etc to see where things change.

What I came up with was this - one window, resizable, and resizing updates a window with the width and height.  For me in chrome on Ubuntu 12.04, I have to set the window for 15px over the actual px dimension that I want because of the scroll bar on the side.  I'm thinking about changing it to allow you to set the default sizes, but resize all the windows, display vertically, and also show rulers above the frames.  I might actually also try to set up something where you could draw guides or boxes around stuff to get pixel dimensions.  Perhaps also some inputs for width and height so that you could resize it numerically instead of dragging.

Today, I was working on adjusting things a bit.  I had set a breakpoint at 799px which changed the menu from a horizontal nav to a button that you clicked on that showed a popup menu.  I was looking at the sizes from responsivator and saw 800px for small tablet, but missed that large tablet portrait was 768px.  The designer asked about how it displayed on his iPad, apparently there it wasn't actually responding either way - it seemed like it was maybe because load was portrait and then window resize was not firing on change of orientation. I was using window size change to set some classes via javascript, I moved those to work a bit differently. 

Since it seemed that the window resize was not being fired on orientation change, I went from applying 'hidden-menu' as a class to my menu to hiding it by default, then using click on the button to add 'visible-menu' to override the hidden aspect.  But before that I was trying a couple different things, not quite sure what I needed to do.  I was asking for some help in the concrete5 IRC channel and once it was explained what I wanted to do, someone pointed out that my whole method for figuring out where breakpoints happened was completely wrong.

The problem that I hadn't thought about was the fact that device width is not constant even when it is the same pixel dimensions.  If you zoom in, your content is larger, but the width is the same, and you have to figure out how to adjust for that.  Apparently the solution is to set your media queries in ems, not pixels - this makes a lot of sense, when you think about it.  Zooming is something that you have to adjust for when designing your site, too.  I had been setting my media queries for pixel widths.  When I checked it, zooming in broke the layout.

I had a base font set to 100% which should be 16px, and for the home page slider I had set all the content to be scaled in ems.  There's a slider called Vegas that I learned about recently that worked perfectly with this designer's view for the home page.  It was a pretty simple thing to modify Attributes Slider to work instead of caroufredsel.  Making a slideshow was really simple, and then using the callback function to show/hide different divs with content for title and text was really simple.  Instead of just the title / wsywig / link that I have in my marketplace add on, I added a bunch more options.  

The first thing that I noticed was that the designs showed different color values for paragraph and header text on each different slide.  So my first inclination was to make it just a single tinyMCE WYSIWYG and call it good.  Then I started adding data, and one of the slides had a white H1 tag.  I set it to white, and the realized 'doh!  you can't read the header in the content block editor!' - totally not a workable option.  So I changed it to a text field for the header and a basic text area for the content.  Then I did a search and found out that jordonlev made a color picker attribute.  I installed the package and associated it with files, added two new attributes, one for header and one for text color.  I probably should have  updated the Attributes Slider install to include those, too, but it's a one off project, and will never go back to a blank slate, so manual addition was fine.  I also set it to align the text left or right.  

The design had two links below the header and text on the slides.  One links to a youtube video, the other is a url.  I set it up so the url is a link attribute from attributes slider, and then the youtube link is just a text area.  The way the site is set up, several different blocks need to launch a full screen modal from a link, so that's another aspect I'm working on.  I still don't know how to do that completely, but I have the basics done so far.  

Part of the problem with the popover for video is actually the same problem that confronted us with the footer on this site - apparently the css 'fixed' property doesn't actually work on a lot of platforms.  So while my design looked fine on my desktop at phone widths, when you were actually on a phone scrolling would move the footer menu bar up over the content, then stopping scrolling it would jump directly into position.  The footer we had is loosely based on the Grey Goose Vodka - the footer stays at the bottom fixed until you scroll down to the bottom, then it scrolls up and shows a secondary footer.  I had this working, but actually viewing it on mobile didn't look good.  When I looked at Grey Goose on my phone, I noticed that the menu changed to a static positioned header with a button that jumps you down to the footer.  Then you see the footer menu, with sub-content sections below it.  We got new layouts from the designer to show this today, but I didn't' get them completely implemented.  

One thing that I noticed on the Grey Goose site was that it exposes a bug on earlier versions of android, but not on iOS.  When you click a link with a #anchor style tag on an android web browser, it scrolls to the link.  However, if you scroll again and then hit the link again, it does _not_ link to the anchor again.  Which makes a header 'jump to navigation' link pretty useless.  And actually I was running into other issues with the header tag, I tried changing it to javascript to do the scroll and not update the browser url but I couldn't get the button to even acknowledge that it was clickable.  Some other element is overriding the new header element that displays on the sub-768-pixel-wide views.  I gave up about 5:15 tonight, I will have to do more work on it Monday.

At any rate, it's turning out that doing a truly responsive design is a lot more complicated that I thought it would be.  Even learning how to specify fonts in ems looks like it will take longer than a normal slice and dice theme job.  I found out that if you have a base font of 16px, then a header of 3em or 48px, if you want a bottom margin of 12px, you don't do a h1 { margin-bottom: 0.75em } relative from 16px, you have to calculate relative to the now valid base of 48px.  So you need to say margin-bottom: .25em.  You have to figure out this calculation for every different font size and margin.  You could do pixels, but again, it doesn't work with zooming in perfectly.  There's something called a rem or 'root em' that you can use to calculate from the base font size, but it's not supported in all browsers.  

So that's more of what I'll have to do next week - changing pixel sizes to ems will take awhile.  

I did get it set up so that zooming would work, but that also took way longer than it should have.  This is because I'd been having some problems with firefox so I switched to chrome as my main browser.  It wasn't working to resize and then zoom, and I spent a lot of time trying to figure it out.  It turns out there's actually a bug in webkit browsers that keeps them from updating when the zoom in function is activated.  I used the suggested javascript fix to apply content to a style tag in the header to force an update on the zoom event.  I still have to check it on an actual tablet, but it seems to be working in chrome on my desktop.

The thing I'm taking away from this project is that there are far more things to think about in a responsive design than I ever thought possible.  I'm learning a ton, but there's still so much more to know.  There are a lot of people out there saying they can make 'responsive' designs, but actually doing everything the way it truly needs to be done to be device agnostic is a really specific thing.  I don't think there are a lot of designers or developers who can really do it well, or completely.