Fred
Brack Raleigh, NC |
This page documents one person's experience in making several websites mobile friendly. "Mobile friendly" means when the site is viewed with an iPhone, Android device, or Windows Phone, the pages will be displayed in larger text with reduced line lengths mostly full-width and most likely with a minimized header and menu structure. I do not present myself as an expert in this area, or in web design in general. I'm just trying to help out folks trying to get started on this task by giving a detailed scenario.
The width of a mobile phone screen, whether held in portrait mode (vertical) or landscape (sideways), is much smaller than any desktop or laptop screen, so displaying a full web page yields very tiny print. When a website supports mobile devices, that means that text will be larger, line lengths will be cut way back, and to the extent possible, everything will fit on the screen without scrolling to the right. It is not unusual today to find that 50% or more of your visitors are using mobile devices when they visit your site, so this is important. (Note: we don't consider "tablets" mobile devices here due to their larger screen sizes.)
The browsers are willing to help narrow the line lengths and increase font size automatically if you include a certain "meta" statement. If you are really lucky, that's all you'll need: a one-statement addition to each web page and you're done! Chances of that happening? Slim. There is also a single STYLE statement (generally implemented via your CSS file) to adapt images to a mobile device. But you will likely have to do several other things, and they are outlined below. OR, if you are using a content management system like Wordpress, Drupal, or Joomla, they will "automatically" take care of mobile support for you (well, mostly).
These solutions involve both CSS and JavaScript. You really don't need to know much about JavaScript; you can take my file and modify just one line and access the file from your individual web pages with a simple one-line Script invocation. But you DO need to know something about CSS: Cascaded Style Sheets. In fact, this approach works primarily via the very concept of "cascaded." There are numerous resources for learning about CSS, but the most popular one seems to be W3Schools. I need to "assume" you are using a style sheet for your website already (or will add one) and you already have or will add CSS IDs or classes to certain elements in your pages. If you don't know anything about CSS, I recommend that you take a pause and learn a little about it before attempting the implementation steps below.
Here are the steps involved in modifying a website to become mobile friendly. Consider them A START! Your own website may be much more complicated, but this will get you started.
Note: For purposes of our implementation discussion, we "assume" that you have some form of "global" header section (masthead and navigation) that automatically propagates to every page; that is, you will make the changes in one file, and those changes (to the header) will propagate to all pages. I use the (now free) Microsoft Expression Web, for example, and in that product the "common code" is contained in something called the Dynamic Web Template (DWT) that can be applied page-by-page or globally. In FrontPage (yes, some of us still use FrontPage!), it is accomplished via an Insert / Web Component / Included Content (a file, implemented via a WEBBOT statement). I know nothing about Adobe's Dreamweaver. If you don't have a common template or included file, then you'll have to modify each page separately to insert the one-line test for mobile and perhaps some ID or Class references, if you don't have them in place already.
Take a simple file on your website, one without tables or pictures, for example, but definitely a full header and navigation area, and copy it over as "test.html" or something like that. You will work with that file to make the basic changes you want to see on every page and perhaps experiment with some of the techniques below before attempting modification of "live" files on your website. Once you are satisfied with the appearance, you can insert the Viewport statement and call to the JavaScript file detailed below on every page on your site, then begin the process of page-by-page analysis.
Meta statements are always added in the <head> section of a web page. They control certain aspects of page presentation or document information about the page. There is ONE statement which can be added to tell your browser to do whatever it can automatically to make your page fit properly on a mobile device, so you will always want to add the following statement anywhere in the <head> section:
<meta content="width=device-width,
initial-scale=1" name="viewport">
Save your file and look at it on your mobile device. If you are satisfied, you're done! More likely, though, you will notice two things:
You solve each of these problems separately; and, of course, just because the test file doesn't have problem #2 doesn't mean other pages won't.
If you have other JavaScript files already, you probably have a "js" subdirectory, and you'll put this file there. If you have a simple website and this is your first JavaScript file, go ahead and put it in the main directory if you like, OR create a new "js" subdirectory and use it.
This "Check4Mobile.js" JavaScript figures out if you are on a mobile device, and if so it calls up an additional CSS file for your page (I call it mobile.css). That CSS file controls all the aspects of your web page that you need to CHANGE DYNAMICALLY to support the mobile device. We'll discuss how it works shortly, but here's the file content:
// Check4Mobile: Determine whether
or not this is a MOBILE device.
// IF YES, set 'mobilePhone' to TRUE and cascade the mobile style sheet.
// The href MUST specify the fully qualified URL address of mobile.css.
var ua=navigator.userAgent;
var mobilePhone=false;
if (ua.indexOf("Android")!=-1) mobilePhone=true;
if (ua.indexOf("iPhone")!=-1) mobilePhone=true;
if (ua.indexOf("Windows Phone")!=-1) mobilePhone=true;
if (mobilePhone) {
var cssmobile='<link href="FULL-PATH/mobile.css"
rel="stylesheet" type="text/css">';
document.write(cssmobile);
}
Right-Click to DOWNLOAD a copy of the above JavaScript File
(Yes, the "var cssmobile" data could be written directly, so do that if you understand how and prefer it! You can also experiment by including the SCRIPT shown directly in your test file, bounded by the appropriate statements.)
The lines beginning '//' are comments which you can leave in the file. You SHOULD supply the full path to your CSS file as shown. (The reason you need the full path is so that if you have HTML files in subdirectories, this statement will always access the absolute address, not the relative one. For example, the href in Check4Mobile.js for THIS webpage is "http://www.bracksco.com/css/mobile.css" which is a level above this page. I could move this page to a different directory and it would still work.) So what this JavaScript does is look for the three types of mobile phone names in the so-called "user agent" of the browser (navigator). While not important to your implementation, just for reference a typical "user agent" line (for an iPhone in this case) looks like this:
Mozilla/5.0 (iPhone; CPU iPhone OS 10_2_1 like Mac OS X) AppleWebKit/602.4.6 (KHTML, like Gecko) Version/10.0 Mobile/14D27 Safari/602.1
Now you need to invoke this JavaScript file in each web page, and you need to do it at the right spot! In the true spirit of "cascading" style sheets (CSS), you MUST MUST MUST cascade this one AFTER all your other style sheets ... because the nature of cascading style sheet is: the last one wins! In other words, the content of THIS style sheet that you are invoking will OVERRIDE the contents of the previous one(s) and thus modify whatever is necessary for proper presentation on a mobile device. So place the following statement AFTER the meta statement(s) which invokes any other style sheet(s):
<script src="js/Check4Mobile.js></script>
You need to adjust the "src" statement to point to wherever your JavaScript file is. For example, remove the "js/" if you put it in the main directory. Depending on what method you use to insert this statement, you may be better off specifying the full path to the .js file like you did for the .css file inside the .js file above.
So ... when this Script file executes, if and only if you are running on a mobile device a new Style Sheet named mobile.css will be cascaded following any other ones you have. Speaking of mobile.css, let's discuss it.
As above for JavaScript, you may very well have a css subdirectory on your website, and that's where this file goes. If not, create one or just add this file to the main directory.
I can't predict the proper content for your mobile.css file; I can only show you an example and tell you how and why to add other statements. In general, though, the purpose of the mobile.css file is to override ID and Class definitions to suppress or modify the appearance of file content on the mobile device. So here is a brief example, followed by an explanation. Please note that while I show a mixture of ID definitions (beginning with '#') and Class definitions (beginning with '.'), use whatever works for you -- they end up having the same results in appearance.
/* mobile.css: Style modifications
to support mobile devices */
/* Everything which follows is an EXAMPLE ONLY!
*/
/* YOU need to decide the exact content.
*/
/* To minimize the heading size, we will suppress logos */
#logoleft { display: none }
#logoright { display: none }
/* Suppress the regular heading and activate a mobile one */
#header { display: none }
#headermobile { display: inline }
/* Eliminate two-column mode */
#left_col { width: 100% }
#right_col { width: 100% }
/* Suppress navigation, because we will do it differently */
table.nav { display:none }
/* Override table widths to 100% */
table.width80m { width: 100% }
/* Provide a generic "don't display on a mobile device" class */
.mobileno { display: none }
/* And a "mobile-only" display option */
.mobileyes { display: inline }
/* NOTE: 'run-in' is dicey - see discussion */
.mobilyesblock { display: block } /* see discussion */
/* Define the characteristics of the mobile title line */
.sitetitlem {
font-family: Verdana, Geneva, Tahoma, sans-serif;
font-size: medium;
font-weight: bold;
color: navy;
background-color: yellow;
text-align: left;
}
/* Provide new class for mobile navigation page */
.mobilenav {
font-family: Verdana, Geneva, Tahoma, sans-serif;
letter-spacing: 2px;
text-align: center;
width: 100%;
margin-top: 0px;
margin-bottom: 0px;
display: list-item;
}
Right-Click to DOWNLOAD a copy of the above sample MOBILE.CSS File
Whew! What's that all about? Here goes ...
A "typical" web page has a common header consisting of a logo on the left, perhaps repeated or showing a different image on the right, and some large text in the middle naming the website or the specific page. There may be additional text in the middle also, or text on the right instead of a second image. Assuming you have used ids (or classes) to define these three areas, you can MODIFY those definitions via the mobile.css. In the case shown above, the first four CSS lines (other than comments) are modifying a website with an image on the left and right and a header in the middle. The images are SUPPRESSED via the "display: none" CSS option (to save space). The header as defined originally is also suppressed, and an ALTERNATE HEADER for the mobile site is activated (by using "display: inline" which is effectively the opposite of "none"). To help you understand this concept better, here is how the header might be defined with IDs which match the CSS above:
<!-- Masthead (Logos and Site
Title) -->
<div id="masthead">
<div id="logoleft">
<img alt="Logo 1" src="images/logo1.gif" height="100"
width="100">
</div>
<div id="logoright">
<img alt="Logo 2" src="images/logo2.gif" height="100"
width="100">
</div>
<div id="header">
<span class="sitetitle"><strong>My Long Website
Title</strong></span><br>
My organization's motto or something like that on second
line
</div>
<div id="headermobile">
<a href="menumobile.html"><img
src="FULL-PATH/images/menu.jpg" alt="Menu"
height="27" width="69" style="vertical-align: middle"></a>
Short Website Title
<hr style="margin-top: 0px; margin-bottom: 0px">
</div>
</div>
<!-- End of Masthead, Beginning of Navigation -->
EXPLANATION:
Moving on to navigation, typically (but not always) this is found at the top of the page right below the masthead. And typically (but not always) it is shown as tabs or options in boxes. If the boxes are created using a table, then they will most likely be wider than the width of a mobile device, and right away you have a problem. Regardless, if there are more than just a few options (the main site I work on has three rows of 5, for a total of 15 navigation options), then this will take up a lot of space. YOU must decide whether or not you need to change the navigation area for your mobile device. The HTML example above continues like this (simplified):
<div id="navigation">
<!-- IF MOBILE, table.nav PROPERTY WILL BE REPLACED WITH display:none -->
<table cellpadding="2" class="nav">
<tr>
<td class="nav">
<a href="index.html">Home</a></td>
<td class="nav">
<a href="about.html">About</a></td>
<!-- and the navigation continues like above ...
-->
</tr>
</table>
</div>
<!--********** End of Navigation, Beginning of Page Body **********-->
OK, CSS purists, don't beat me up for showing a table for navigation! That's not important here. Also note that the class="nav" in the TD is a different CSS definition from the same class at the table level. When you suppress display at the table level, TD definitions don't matter. In other words, we just suppressed the entire navigation block via the mobile.css entry "table.nav { display:none }". Note: Another way to do this is simply place class="mobileyes" or class="mobileno" on the DIV statement.
<div id="headermobile">
<a href="menumobile.html"><img
src="FULL-PATH/images/menu.jpg" alt="Menu"
height="27" width="69" style="vertical-align:
middle"></a>
Short Website Title
<hr style="margin-top: 0px; margin-bottom: 0px">
</div>
In our example, mobile navigation will be moved to a SEPARATE PAGE, mobilemenu.html, accessed via a URL link under the Menu image in the mobile header, as defined above under ID (or Class) "headermobile". In other words, the new header for our mobile devices looks like this (minus the bar underneath, which was hard to reproduce here):
... and if you click the Menu icon (which you can do here if you like), you'll get a separate web page with nothing but the site navigation options centered in a list. The class definition for that page is shown in mobile.css above as mobilenav, and the menu page itself (menumobile.html) consists of lines that look like this:
<h2 class="pagetitle">Menu</h2>
<p class="mobilenav">
<a href="index.html" title="My Website Home Page">Home</a><br>
<a href="about.html" title="About My Website">About</a><br>
<!-- ... more of same ... -->
</p>
Feel free to "steal" my Menu image above by right-clicking on it and downloading it. I designed it myself, so there is no copyright concern.
In March 2018 I revamped my approach to mobile navigation somewhat. Someday I'll revise the above section, but for now, I'll just summarize here.
Keep in mind that you can make ANY section of code unique to mobile or non-mobile devices by the use of class="mobileyes" or class="mobileno" with a <div> surrounding the affected code.
So I separated mobile and regular header and navigation completely, doing away with the requirement for modifying the nav class, for example.
I also wanted to freeze the top and bottom lines on the screen for mobile, so getting back to the Menu was easy, as was hitting the TOP button at the bottom of each screen. This is done by using position: fixed in the CSS definition of the mobile title and/or footer lines.
By adding top: 0px to the top line definition and bottom: 0px to the bottom line definition (along with position: fixed), the positions on the screen get locked.
You can examine my mobile CSS file at http://acb.org/adp/css/mobile.css. Look at .sitetitlem and #footerm.
There was one glitch: to keep the body text below
the title line from scrolling on top of the title, I had to add the
following statement immediately after the title line HTML for mobile (but
don't ask me why):
<p style="line-height: 1px"> </p>
And then in July 2018, I discovered a problem. The run-in option of display is supposed to adapt to either inline or block, but it does not seem to do so. I don't want to go into the difference here; but if in using the mobileyes class you find what you expect to happen doesn't (e.g., centering a paragraph, which is a block operation), then use the mobileyesblock option instead to force block mode.
Whew again! Once you have completed the installation and testing of the JavaScript and mobile.css files AND figured out what you are going to do about navigation, you can begin implementation sitewide. I recommend you do this page-by-page, figuring out what techniques are necessary to get pages displaying to your satisfaction. Some ideas for this follow.
Inevitably, when you look at your mobile website, some pages will run their lines off-screen, and in particular, tables will extend off-screen to the right. These are some of the situations you may find and suggestions on how to correct them.
Here's an interesting example of a solution for a page in which the author happened to have many long URLs listed out in unordered lists. This was implemented originally in a <style> section in the <head> of the page for testing, then moved to the mobile.css file to apply universally across the website:
li { overflow-wrap: break-word }
Note that the CSS does NOT start with a period or hash-tag. It overrides the default system definition of the list item tag to allow breaking long words. (This used to be called word-wrap, but the correct name is overflow-wrap.)
Sometimes you may find a big hunk of text (or even tables or images) that you can do without on a mobile device. You do this by using a class which says basically, "mobile only." The opposite is also true: a class which say "non-mobile only." These classes are defined in the CSS example above as:
/* Provide a generic "don't
display on a mobile device" class */
.mobileno { display: none }
/* And a "mobile-only" display option */
.mobileyes { display: inline } /* but note discussion about this... */
To suppress a paragraph, add "class="mobileno" to the paragraph tag. To suppress EVERYTHING in a certain area, put it in a DIV. Examples:
<p class="mobileno">This will not
display on mobile.</p>
<div class="mobileno">
<!-- nothing here will display on mobile -->
</div>
Another example would be suppressing an image which is too large:
<img class="mobileno" alt="Our Office" src="images/office.jpg" height="300" width="600">
That line says, if we are on MOBILE, then NO, don't display this image. But you MIGHT choose instead to offer a smaller image for mobile on the very next line:
<img class="mobileyes" alt="Our Office" src="images/office.jpg" height="100" width="200">
BTW, my iPhone 7 appears to support an image of 300 pixels wide.
IMPORTANT! You can add ONE STATEMENT to your primary CSS file which will cause images to self-adapt to mobile screens:
img { max-width: 100%; width: auto; height: auto; }
Another thought: suppose you have a table which you simply can't reduce enough to fit on the screen. You could write something similar to the following which would only display on a mobile device:
<p class="mobileyes">Attention
Mobile Users: The table below is too wide for normal display,
but the third column is generally not of key interest; so either ignore it
or turn your
mobile device sideways to read the full width.</p>
To understand your options, keep in mind there are three basic table tags: <table>, <tr>, and <td>. You can add "class="mobileno" to any of them. If you add it to the <table> tag, the entire table will be suppressed. If you add it to the <tr> tag, the entire row (of imbedded <td> cell definitions) will be suppressed. If you add it to the <td> tag, the entire column will be suppressed, provided you add it to every cell in that column. However, you may find that your web management program (e.g., MS Essentials Web) will act very strangely and not display what you will ultimately see via your browser! You do have the oddity of the closing tag not being suppressed, so that may cause validation errors.
Caution: there is a "gotcha": There is no CSS equivalent for the table colspan option. So if you have any data in your table that spans multiple columns, you cannot eliminate one or more columns of data. (Well, you can eliminate them, but the column-spanned row will look awful.) Trying to add "class="mobileyes" and "class="mobileno" to two consecutive <td> tabs with different column spans will not work either (again, the results will look awkward but it may be better than nothing...), and you will fail validation.
In July 2019 I had to face up to this colspan problem, and here's what I did. I suppressed everything in the first column (via "class="mobileno" on either an img statement or by putting a <span class="mobileno"> around text). Thus in mobile a first column of near-zero width exists, but I get no validation errors.
Ultimate the primary value of these options is to eliminate either an entire table (which could also be done via a DIV), or to eliminate one column (say the far right) if it has low-value data, so the table fits better on the screen.
Here's an interesting approach to handle a two-column table in which it is not important to pair the data in the left column with the data in the right. I use tables sometimes as an easy method of splitting something into two columns just to save space (for example, a long bulleted list); but then the second column causes width problems for mobile, especially when images are involved. So here's my solution: Use "class="mobileno" on the <td> for the second column to suppress it; but then use "class="mobileyes" for a second <tr> (which will suppress the entire row for non-mobiles) and repeat the second column data in that new row.
<table>
<tr> [first row]
<td> [first column]
... first column data ...
</td>
<td class="mobileno">
[second column, suppressed for mobile]
... second column data ...
</td>
</tr> [end of first row]
<tr class="mobileyes">
[second row, mobile only]
<td> [second row, first column]
... second column data repeated
...
</td>
</tr>
</table>
In CSS (as opposed to using a table), the "normal" way to display text in two columns is to "float" text to the left or right; something like this:
<div id="left_col">
<h2 class="article">First Article</h2>
<p>Text of article 1 ... </p>
<!-- repeat above for next article, etc. -->
</div>
<div id="right_col">
<h2 class="article">Fifth Article</h2>
<p>Text of article 5 ... </p>
<!-- repeat above for next article, etc. -->
</div>
The regular CSS definitions of the columns might include:
#left_col {
float: left;
width: 50%;
position: relative;
clear: both;
}
#right_col {
float: right;
width: 49%;
position: relative;
text-align: left;
}
If you try to display a page with two columns on a mobile device, it will look awful; so you need to "defeat" the columns. You do this simply as shown in our original mobile.css example:
/* Eliminate two-column mode */
#left_col { width: 100% }
#right_col { width: 100% }
Now the text in the right column will simple begin after left column text has been displayed (full-width).
I personally like to make tables narrower than full-screen and center them. So I would typically include the option WIDTH=80% (or some other number) as part of the table definition. By changing that to a CSS CLASS, you can make the table full-width for mobile devices using something like "<table class="width80m" ...>". So, for example, my main CSS file has this statement (with the "m" meaning it is different for mobile):
table.width80m { width: 80% }
... and my mobile.css file has this statement overriding it:
table.width80m { width: 100% }
Normally list items "<li>" are indented. On mobile, this takes up precious space. You can eliminate that space by creating the following class definition in your mobile CSS file. (Credit for this idea goes to Jpsy in StackOverflow, a good place to get CSS questions answered. He points out, though, that the exact spacing varies by browser; so this may not fully butt the bullet up against the left column for you. This is the "safe" value.)
.justifym { padding-left: 1.2em }
... then start your list with:
<ul class="justifym">
(We didn't start the class with ul so that it could be used with ol also ...)
Interestingly enough, when I tested this page, I found the fact that I indented the sample code was annoying on mobile, so I gave each affected paragraph its own class ("indentex") and specified an indent in the main CSS file (.indentex { margin-left: 20px }) and no indent in the mobile CSS file (.indentex { margin-left: 0px }). In other words, the sample code above is coded this way:
<p class="indentex"><span class="example">.justifym { padding-left: 1.2em }</span></p>
I should also point out that CODE EXAMPLES like this don't look great on a mobile device, because line-wrapping makes it harder to tell where one line ends and another begins; but hopefully most people won't be reading this from a mobile device (although I urge you to take a look to see what it happens and how mobile presentation looks, since that's what this page is about!).
As I find them, I'll add sites that address issues that I don't cover above.
I hope this tutorial has been helpful in getting you started to support your website on mobile devices. If you have any feedback on corrections or better implementations of the concepts above, feel free to write me at the address below. If you want to view the primary website which I modified to support mobile, please visit the Audio Description Project ... on both your desktop and mobile device! (And now I've finally gotten around to working on my own pages, too...)
Fred