Share Tweet Reccomend

Better List Item Grid Tiles with CSS

One of the more common ways that you see collections of items displayed on the web are tile based layouts. Usually these tiles will consist of a container with an image and some sort of descriptive text below the image or as an overlay. Accomplishing this sort of layout in HTML and CSS is not particularly difficult but in some scenarios there are some interesting challenges to tackle, especially when it comes to responsive views. We will explore some of these in what follows.

Certainly in doing a layout of tiles you could use the grid of a CSS framework like Bootstrap or Foundation to put each individual tile into a grid column. But there are, shall we say, annoyances that come with trying to do this. For one thing, because Bootstrap is on a system of rows and grids you will have to count the number of items as they come back to figure out when to close out one row and start a new one. For example, if you wanted a two column grid of items and you were returning markup from the server you would have close out the Bootstrap row on every second item. We’ll be using PHP in our example. I do realize that normally in a production-grade app you would not (or should not) mix this UI content with your server sided logic like we do below. You’d probably use a templating engine of some sort. But this is just an example for the purposes of illustration… and developers do mix these two components together at times as I am sure you are probably aware.

So let’s say we have an associative array $data that has a “text” property as one of its keys. We could print the value of each item in our set in a Bootstrap grid layout like so…

$count = 0;
foreach ($data as $item) {
    if($count == 0) {
        $markup .= '<div class="row">';
    }
    $markup .= '<div class="col-md-6">'. $item["text"] .'</div>';
    if ($count++ %2 == 0) {
        $markup .= '</div>'
        $count = 0;
    }
}

Which might give us something like what we see here.

This works but it seems a bit awkward and weird. Because we are using a 2 column grid we have to count every other item and close out the row before starting a new row. If we wanted a 3 column grid we’d have to count every 3 items and so on. This might work okay in some scenarios, but in others we may not have the luxury of being able to use the Bootstrap grid with ease and consistency. What if, say, these results that we currently have could also be appended to via AJAX calls? You see a lot of this sort of thing on sites like Pinterest or Instagram and their infinite scrolling capabilities. As you scroll to the bottom more content gets loaded dynamically from the server from client side calls made in JavaScript.

The point is if you use Bootstrap and want to keep the layout consistent you’re going to have to always be keeping track of how many items you have and where you are in the Bootstrap row closing and opening phase. It’ gets a bit messy and awkward to maintain as functionality gets a bit more dynamic and complex. There probably is, for lack of a better term, a “cleaner” implementation we can take a look at.

Read More »

Share Tweet Reccomend

Local Search with RegEx

I was developing an HTML5 mobile app for an organization. The app was very simple and essentially consisted of a number of different chapters with a lot of text in each. So the homepage of the app was just a list of the chapters and each list item linked to a chapter page. All the text was in a single page (HTML document) and the app framework would just show/hide the relevant portions of it when needed. A lot of mobile HTML5 frameworks do this implementation and it essentially amounts to a simple single page application. None of the content for this app was stored on a server.

However, one of the features requested was search in that they wanted the ability to search for a term and link to the term from a search page. This is usually pretty easy if content is stored in a database because all the infrastructure to run queries against content in said database is there for you. However if all the text is in a single page application, how would you 1. find it and 2, link to it? What follows is essentially my approach in what amounts to essentially a local search functionality in a single page application.

For starters, say we had the following HTML document…

<!doctype html>
<html>
  <head>
    <title>App</title>
  </head>
<body>
    <div id="home" class="page">
        <ul id="menu" class="page">
            <li><a href="#search">Search</a></li>
            <li><a href="#chapter1">Chapter 1</a></li>
            <li><a href="#chapter2">Chapter 2</a></li>
            <li><a href="#chapter3">Chapter 3</a></li>
        </ul>
    </div>
    <div id="chapter1" class="page">
        <p>The quick brown fox jumped over the lazy dog.</p>
        <p>How now brown cow?</p>
        <p>Something else</p>
    </div>
    <div  id="chapter2" class="page">
        <p>Chapter 2 text here...</p>
        <p>More text here...</p>
    </div>    
    <div  id="chapter3" class="page">
        <p>Chapter 3 text here...</p>
        <p>More text here...</p>
    </div> 
    <div id="search" class="page">
        <input id="search-box" type="search" />
        <ul id="search-results"></ul>
    </div>   
</body>
</html>

Each div with the class “page” would be loaded into the main view when a user clicked on a link to the id of the <div> as can be seen in the menu page. For brevity, I’ve kept the content of each <div> really small but imagine that there were a number of chapters and each paragraph in each chapter had large amounts of text.

What I ended up doing is I added a class called “indexed” (to say that the content of this element is going to be indexed in the search functionality) and some “data-reference” attributes to each paragraph of text to be able to tell where in the application I was. If we were going to have for text *with links*, we’d need to have a way to tell “where we are” so that when we load that page we could scroll to the div that had the text that was searched for.

<!doctype html>
<html>
  <head>
    <title>App</title>
  </head>
<body>
    <div id="home" class="page">
        <ul id="menu" class="page">
            <li><a href="#search">Search</a></li>
            <li><a href="#chapter1">Chapter 1</a></li>
            <li><a href="#chapter2">Chapter 2</a></li>
            <li><a href="#chapter3">Chapter 3</a></li>
        </ul>
    </div>
    <div id="chapter1" class="page">
        <p class="indexed" data-reference="1-1">The quick brown fox jumped over the lazy dog.</p>
        <p class="indexed" data-reference="1-2">How now brown cow?</p>
        <p class="indexed" data-reference="1-3">Something else</p>
    </div>
    <div  id="chapter2" class="page">
        <p class="indexed" data-reference="2-1">Chapter 2 text here...</p>
        <p class="indexed" data-reference="2-2">More text here...</p>
    </div>    
    <div  id="chapter3" class="page">
        <p class="indexed" data-reference="3-1">Chapter 3 text here...</p>
        <p class="indexed" data-reference="3-2">More text here...</p>
    </div> 
    <div id="search" class="page">
        <input id="search-box" type="search" />
        <ul id="search-results"></ul>
    </div>   
</body>
</html>

So as the user types into the search box if we use some jQuery and some RegEx we can 1. search through every “indexed” element for the text that was searched for and 2. populate the search results <div> with links to the various elements. It would look a little bit like this…

jQuery(document).ready(function(){
    function search(searchedText) {
        if(searchedText.trim() === ""){
            jQuery('#search-results').empty().text('No results...');
            return;
        }
        var res = jQuery(".indexed:contains('"+searchedText+"')").each( function() {
            var current = jQuery(this).closest('div[class="page"]');
            var regex = new RegExp(".{0,20}" + searchedText + ".{0,20}", "i");
            var str = jQuery(this).text().match(regex);
            var ref = jQuery(this).closest('[data-reference]');
            jQuery('#search-results').append('<li><a href="#'+ current.attr('id') +'?reference='+ ref.attr('data-reference') +'">... '+ str +' ...</a> - '+ current.find('h1').text() +'</li>');
            return; 
        });
        if(res.length === 0) {
            jQuery('#search-results').empty().text('No results...');
        }
    }
    var searchResults = jQuery('#search-results'), searchTimeout;
    jQuery('#search-box').on('keyup', function(){
        var el = jQuery(this);
        searchResults.empty();
        clearTimeout(searchTimeout);
        searchTimeout = setTimeout(function() {
            search(el.val());
        }, 1000);
    });
});

So basically what we are saying here is that while we type into the search box, we will wait until the user is finished typing and then we will check each “indexed” element for the text we are searching for. If we find it we will create a link to that text to the chapter and append a query string value to the “data-reference” value of the element that contains the text. We can then use the event that fires every time the page changes (as a lot of mobile frameworks have) to check for this reference parameter in the url. If it is there we can do something like the following to scroll to the paragraph that contains the text we were searching for. We call the following scrollTo function on each change/load of a page.

function getParameter(name){
    var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location);
    return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
}
function scrollTo() {	
    if(getParameter('reference')) {
        jQuery('html,body').animate({
            scrollTop: jQuery('[data-reference="'+ getParameter('reference') +'"]').prev().offset().top -20
        }, 100);            
    }
}

The way things are set up at the moment, the regular expression will search for the exact text entered into the search box. Thus, search is case-snesitive at the moment. No matter. If we wanted to incorporate case-insensitivity into things we could simply add the following method…

// make :contains case insenstive for search
jQuery.expr[":"].contains = jQuery.expr.createPseudo(function(arg) {
    return function( elem ) {
        return jQuery(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;
    };
});

By implementing these sorts of techniques and methods, you can incorporate local search and linking into a single page application with a relatively small amount of code. You could take this and expand upon it pretty easily. So even within the perceived limitations of a single page application, you can find ways to implement dynamic functionality that you would expect from any other application. Until next time, happy searching!

View Demo
Share Tweet Reccomend

Responsive Grid Rowspan

If you have been doing anything with front-end web development since ca. 2010 you will have no doubt come across the concept of responsive web development and along with it, responsive grids. Responsive grids are great and, as of early 2015, have become completely ubiquitous across the Internet. Whether you are using Twitter Bootstrap or ZURB Foundation or any one of the numerous lesser-known responsive grid systems they all provide a nice way to clreate flexible fluid web layouts that display well on all devices.

Fluid responsive grids are not without their drawbacks, however, Their structure tends to bring about some challenges in doing some more complex positioning of content. For example, if one column in a group of columns placed next to each other in a row has more content than adjacent columns, you can have some unwanted effects in your layout. For example, in the example below (using Twitter Bootstrap), we can see that with more content in the right column the left column will get pushed down.

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Responsive Grid Rowspan</title>
<link rel="stylesheet" type="text/css" href="css/style.css" />
</head>
<body>
    <div class="row">
        <div class="col-lg-8">
            <div class="inner">
                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras ut justo vel ante fringilla accumsan quis et est. In euismod convallis porta. Mauris condimentum sapien erat, et scelerisque velit dapibus ut. Cras et blandit justo. In laoreet sapien et nulla bibendum, ac fermentum massa lacinia. Etiam ornare est lectus, et posuere velit elementum sed. Fusce sed felis ante. Integer consequat bibendum mi ut porta. Nulla quis egestas est.</p>
            </div>
        </div>
        <div class="col-lg-4">
            <div class="inner" style="background:#999;">
                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras ut justo vel ante fringilla accumsan quis et est. In euismod convallis porta. Mauris condimentum sapien erat, et scelerisque velit dapibus ut. Cras et blandit justo. In laoreet sapien et nulla bibendum, ac fermentum massa lacinia. Etiam ornare est lectus, et posuere velit elementum sed. Fusce sed felis ante. Integer consequat bibendum mi ut porta. Nulla quis egestas est.</p>
                <p>Duis ac risus congue, interdum felis sed, maximus ligula. Aenean mollis convallis libero, non efficitur justo blandit vel. Proin ultrices orci massa, vel pharetra ex convallis in. Mauris fringilla ullamcorper nibh a auctor. In consectetur justo sed tellus iaculis, in vehicula nibh sodales. Nullam tincidunt dignissim odio at vestibulum. Nullam in eros nisl. In vel arcu quis lacus pellentesque rhoncus. Suspendisse quis diam auctor, maximus odio sed, malesuada nulla. Duis rhoncus lorem elit, hendrerit volutpat eros suscipit ac. Cras id magna dui. Donec sit amet massa non libero malesuada sodales sit amet sed sapien. Praesent in arcu ut quam faucibus vehicula non at ligula.</p>
            </div>
        </div>
    </div>
    <div class="row">
        <div class="col-lg-8">
            <div class="inner">
                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras ut justo vel ante fringilla accumsan quis et est. In euismod convallis porta. Mauris condimentum sapien erat, et scelerisque velit dapibus ut. Cras et blandit justo. In laoreet sapien et nulla bibendum, ac fermentum massa lacinia. Etiam ornare est lectus, et posuere velit elementum sed. Fusce sed felis ante. Integer consequat bibendum mi ut porta. Nulla quis egestas est.</p>
              <p>Duis ac risus congue, interdum felis sed, maximus ligula. Aenean mollis convallis libero, non efficitur justo blandit vel. Proin ultrices orci massa, vel pharetra ex convallis in. Mauris fringilla ullamcorper nibh a auctor. In consectetur justo sed tellus iaculis, in vehicula nibh sodales. Nullam tincidunt dignissim odio at vestibulum. Nullam in eros nisl. In vel arcu quis lacus pellentesque rhoncus. Suspendisse quis diam auctor, maximus odio sed, malesuada nulla. Duis rhoncus lorem elit, hendrerit volutpat eros suscipit ac. Cras id magna dui. Donec sit amet massa non libero malesuada sodales sit amet sed sapien. Praesent in arcu ut quam faucibus vehicula non at ligula.</p>
            </div>
        </div>
        <div class="col-lg-4">
            <div class="inner">
              <p>Duis ac risus congue, interdum felis sed, maximus ligula. Aenean mollis convallis libero, non efficitur justo blandit vel. Proin ultrices orci massa, vel pharetra ex convallis in. Mauris fringilla ullamcorper nibh a auctor. In consectetur justo sed tellus iaculis, in vehicula nibh sodales. Nullam tincidunt dignissim odio at vestibulum. Nullam in eros nisl. In vel arcu quis lacus pellentesque rhoncus. Suspendisse quis diam auctor, maximus odio sed, malesuada nulla. Duis rhoncus lorem elit, hendrerit volutpat eros suscipit ac. Cras id magna dui. Donec sit amet massa non libero malesuada sodales sit amet sed sapien. Praesent in arcu ut quam faucibus vehicula non at ligula.</p>
            </div>
        </div>
    </div>
</body>
</html>

It would be great if we could have sort of a “rowspan” effect where we could fit the content nicely together. Fortunately, with a little reordering of the columns and floating the column right, this can be done in an elegant CSS only manner. We’ll move the grid in the second row into the same row as our column with a lot of content. From there we can apply a float:right to the second column.

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Responsive Grid Rowspan</title>
<link rel="stylesheet" type="text/css" href="css/style.css" />
</head>
<body>
    <div class="row">
        <div class="col-lg-8">
            <div class="inner">
                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras ut justo vel ante fringilla accumsan quis et est. In euismod convallis porta. Mauris condimentum sapien erat, et scelerisque velit dapibus ut. Cras et blandit justo. In laoreet sapien et nulla bibendum, ac fermentum massa lacinia. Etiam ornare est lectus, et posuere velit elementum sed. Fusce sed felis ante. Integer consequat bibendum mi ut porta. Nulla quis egestas est.</p>
            </div>
        </div>
        <div class="col-lg-4 rowspan">
            <div class="inner" style="background:#999;">
                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras ut justo vel ante fringilla accumsan quis et est. In euismod convallis porta. Mauris condimentum sapien erat, et scelerisque velit dapibus ut. Cras et blandit justo. In laoreet sapien et nulla bibendum, ac fermentum massa lacinia. Etiam ornare est lectus, et posuere velit elementum sed. Fusce sed felis ante. Integer consequat bibendum mi ut porta. Nulla quis egestas est.</p>
                <p>Duis ac risus congue, interdum felis sed, maximus ligula. Aenean mollis convallis libero, non efficitur justo blandit vel. Proin ultrices orci massa, vel pharetra ex convallis in. Mauris fringilla ullamcorper nibh a auctor. In consectetur justo sed tellus iaculis, in vehicula nibh sodales. Nullam tincidunt dignissim odio at vestibulum. Nullam in eros nisl. In vel arcu quis lacus pellentesque rhoncus. Suspendisse quis diam auctor, maximus odio sed, malesuada nulla. Duis rhoncus lorem elit, hendrerit volutpat eros suscipit ac. Cras id magna dui. Donec sit amet massa non libero malesuada sodales sit amet sed sapien. Praesent in arcu ut quam faucibus vehicula non at ligula.</p>
            </div>
        </div>
        <div class="col-lg-8">
            <div class="inner">
                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras ut justo vel ante fringilla accumsan quis et est. In euismod convallis porta. Mauris condimentum sapien erat, et scelerisque velit dapibus ut. Cras et blandit justo. In laoreet sapien et nulla bibendum, ac fermentum massa lacinia. Etiam ornare est lectus, et posuere velit elementum sed. Fusce sed felis ante. Integer consequat bibendum mi ut porta. Nulla quis egestas est.</p>
              <p>Duis ac risus congue, interdum felis sed, maximus ligula. Aenean mollis convallis libero, non efficitur justo blandit vel. Proin ultrices orci massa, vel pharetra ex convallis in. Mauris fringilla ullamcorper nibh a auctor. In consectetur justo sed tellus iaculis, in vehicula nibh sodales. Nullam tincidunt dignissim odio at vestibulum. Nullam in eros nisl. In vel arcu quis lacus pellentesque rhoncus. Suspendisse quis diam auctor, maximus odio sed, malesuada nulla. Duis rhoncus lorem elit, hendrerit volutpat eros suscipit ac. Cras id magna dui. Donec sit amet massa non libero malesuada sodales sit amet sed sapien. Praesent in arcu ut quam faucibus vehicula non at ligula.</p>
            </div>
        </div>
    </div>
</body>
</html>

And there you have it. With a little bit of finagling, you can get slightly more interesting layouts with a grid. You can see the result of this here…

View Demo »
Share Tweet Reccomend

Crunching Tables, Hidden Data

Should I give up, or should I just keep crunching tables, even if it leads nowhere?

Ah tables… a fascinating piece of Internet history. Originally conceived for the purposes of displaying data, once upon a time, tables, due to their stability, were even the dominant design structure of the Internet. But now with so many other options for both design and displaying data in the HTML DOM, tables are a relic of the past, right?

A lot of times, it seems like this is true. However, there are still situations you run into where you’ll come across tables in legacy systems that still use them as a holdover from past older versions of the product, or even more modern data-display centric systems. One example of this is actually a pretty popular large-scale solution among a diversity of organizations. I won’t name any names, but it rhymes with “Icrosoft Airpoint”

Tables have issues with the fact that the web has been going more mobile since the latter half of the 2000’s and thus, display and viewing areas have been getting smaller. The difficulty with this is that tables are, by their nature, not a particularly fluid data structures. They can be flexible to an extent, but at some point they just decide to say “no más” and they’ll overflow their container content areas… which usually equals some fun side-scrolling.

So here we’ll enter into a discussion of some issues with tables and what can be done to solve them. It seems like the natural approach that a lot of developers will take toward tables to set the width to 100% in the CSS.

table{
width:100%;
}

This is fine up to a certain point as shown in the first example here.

However as the number of columns grow or the data within them start to contain more data that’s not really “breakable” e.g. long words or even hyperlinks eventually tables just overflow their containers as shown in the next example.

Setting width:100%; in your CSS does nothing. Even setting a fixed width such as width:500px; doesn’t do much good either.

What can be done? Well there are a number of solutions perhaps not all of them ideal, but if you’re stuck using tables and you don’t have much choice in turning to something else, what follows can be helpful, at least a little bit.

Solution #1: Crunch it in There
Surprisingly, there is a way to actually ensure that your table does fit the content area. This can be accomplished by setting the table-layout property to “fixed”.

table{
table-layout: fixed;
}

There is a downside to this: all the columns now have the same width. Although this looks okay, it can actually be improved upon a bit further by adding the word-wrap: break-word, property.

table{
table-layout: fixed;
word-wrap: break-word;
}

You could even go a bit further and hide overflowing content in your table header cells and table data cells.

table tr th, table tr td {
overflow:hidden;
}

This, like other solutions with tables does not seem ideal. However, if there is a need to crunch your entire table into a small section, this can be a compromising way to do it.

Solution #2: Side-Scroll
By adding overflow-x: scroll to your container div that your table lives within you can get a little bit of side-scrolling action on.

.container {
overflow-x:scroll
}

Solution #3: Show Less Content
The other option would be to show less content. This can be done by either setting class names on the columns and cells and then hiding the ones you don’t want to show at smaller resolutions (such as those found on mobile devices) by making use of CSS3 media queries.

Solution #4: JavaScript
Another option would be to use a JavaScript/jQuery plugin of some sort to either rearrange your table data or show a limited amount in certain circumstances.

All in all you do have a number of choices you can pick from in dealing with tables, especially when you have to make design decisions pertaining to mobile devices. What the best option is for your particular solution will probably depend on a number of things, but hopefully some of the ones discussed above will give you a good starting point to jump off from.

Share Tweet Reccomend

Web Storage: Local Storage & Session Storage

In the transition from HTML4 to HTML5, one of the additions of note is web storage. Web storage comes in 2 forms: local storage and session storage (the difference between the 2 will be explained subsequently). But first let’s cover the basics. What is web storage? Basically, it is a method of storing data locally in the user’s browser using key value pairs of data like so…

localStorage.setItem('food', 'Burgers');
localStorage.getItem('food'); // Burgers

By setting a key (food), we can store a value (Burgers) locally.

But what’s so different about this? Browser cookies also accomplish this and cookies have been around forever. Good question. There are 2 key differences between web storage and cookies mainly having to do with size capacity and data transfer.

Read More »