Lynda Damiata

 

By | December 15th, 2011 |
smashingmagazine.com ::

A few concerns keep bobbing up now and then for Web developers, one of which relates to how to lay out a given design. Developers have made numerous attempts to do so with existing solutions. Several articles have been written on finding the holy grail of CSS layouts, but to date, not a single solution works without major caveats. At the W3Conf, I gave a talk on how the CSS Working Group is attempting to solve the concerns of Web developers with multiple proposals. There are six layout proposals that are relevant to us, all of which I described in the talk:

Here is a little more about these proposals and how they will help you in developing websites in the future.

Generated Content For Paged Media

This proposal outlines a set of features that would modify the contents of any element to flow as pages, like in a book. A video demonstration shows how to use paged media to generate HTML5 slideshows (look at the demos for GCPM in the Opera Labs Build to play with the features more). To make the content of an element be paged, you would use this syntax:

@media paged {
html {
width: 100%;
overflow-style: paged-x;
padding: 5%;
height: 100%;
box-sizing: border-box;
}
}

This would make the content look something like this:

Here, @media paged indicates that the browser understands paged media and that all of the selectors specified for it should have their styles applied when paged media is supported. Then, you indicate which selector you want to be paged (in the above example, the selector is the html element itself) by specifying the property overflow-style: paged-x. This will simply make the content paged; if you want paged controls to be visible, you need to specify overflow-style: paged-x-controls.

The properties break-before, break-after break-inside can be used to control where the content falls within the pages. For example, if you want headings to only appear with their corresponding content and never at the end of the page or standing alone, you can specify that:

h3, h2 {
break-after: avoid;
}

This ensures that if a heading occurs on the last line of a page, it will be pushed to the next page with the content that it introduces.

API

Two properties are available on an element whose content is paged: currentPage and pageCount. You can set the currentPage property via JavaScript, which would trigger a page change on that element. This would then trigger an onpagechange event on that element, which you could use to run other scripts that are required when the page changes. The pageCount property stores the total number of pages in the paged element. These properties are useful for implementing callbacks that should be triggered on page change; for example, to render notes for a particular slide in a slide deck.

Multiple Columns

Multiple columns are now available in most browsers (including IE10!), which makes them pretty much ready to use on production websites. You can render the content of any element into multiple columns simply by using column-width: <length unit> or column-count: <number>. As with paged content, you can use break-before, break-after or break-inside to control how the content displays within each column. You can also make one of the child elements span the whole set of columns by using column-span: all. Here is how that would look:

Columns are balanced out with content by default. If you would prefer that columns not be balanced, you can set that by using column-fill: auto property. Here is an example of the default behaviour (i.e. column-fill: balanced):

column fill automatic

Note that the last column is empty, and each column is filled one after the other.

Regions

The closest equivalent to regions would be InDesign’s linking of text frames. With the properties in this proposal, you can make the content of selected elements flow through another set of elements. In other words, your content need not be tied to the document flow any longer.

To begin, you need to select elements whose content will be part of a “named flow,” like this:

article.news { flow-into: article_flow; }

Here, all of the content in the article element with the class name news will belong to the flow named article_flow.

Then, you select elements that will render the contents that are part of this named flow:

#main {
flow-from: article_flow;
}

Here, the element with the ID main will be used to display the content in the flow named article_flow. This element has now become a region that renders the content of a named flow. Note that any element that is a region establishes new “block-formatting contexts” and “stacking contexts.” For example, if a child element is part of a flow and is absolutely positioned, it will now only be absolutely positioned with respect to the region it belongs to, and not to the whole viewport.

You can also tweak the styles of content that flows through a region:

@region #main {
p { color: indianred; }
}

region styling

API

An interface named getNamedFlow and an event named regionLayoutUpdate are available for elements that are regions.

getNamedFlow

This returns the flow that that particular region is associated with. The properties available are:

  • overflowA read-only boolean that tells you whether all of the content of the named flow fits within the regions that are part of the flow or whether it overflows.
  • contentNodesA NodeList of all the content elements that belong to the flow.
  • getRegionsByContentNodeThis returns all of the regions that a particular content element would flow through. A very long paragraph might flow through more than one region; with this method, you can retrieve all of the regions that that paragraph element flows through.
  • regionLayoutUpdateThis event gets triggered every time an update is made to the layout of a region. If the region’s dimensions are altered, then the child content elements that are part of that region might alter, too (for example, a few might move to another region, or more child elements might become part of the region).

Exclusions

  • Draft specification (a combination of two proposals: “Exclusions” and “Positioned Floats”)
  • Demo
  • Browser support: IE 10+

Exclusions allow inline content to be wrapped around or within custom shapes using CSS properties. An element becomes an “exclusion element” when wrap-flow is set to a value that is not auto. It can then set the “wrapping area” for inline text outside or within it, according to various CSS properties. The wrap-flow can take the following values: left, right, maximum,both, clear or the default value of auto. Here is how each of these values would affect the inline content around the exclusion element:

exclusion wrap side auto

wrap-flow: auto

exclusion wrap side right

wrap-flow: right

exclusion wrap side both

wrap-flow: both

exclusion wrap side clear

wrap-flow: clear

exclusion wrap side maximum L

wrap-flow: maximum

The wrap-margin property can be used to offset the space between the boundary of the exclusion element and the inline text outside of it. The wrap-padding property is used to offset the space between the boundary of the exclusion element and the inline text inside it.

exclusion padding margin

In the above image, the space between the content outside of the red dashed circular border and the black text outside of it is determined by the wrap-margin, while the space between the red dashed circular border and the blue text within it is determined by the wrap-padding.

Now comes the fun part: specifying custom shapes for the wrapping area. You can use two properties: shape-outside lets you set the wrapping area for inline text outside of the exclusion element, while shape-inside lets you set the wrapping area for inline text inside the exclusion element.

exclusion shapes

Both of these properties can take SVG-like syntax (circle(50%, 50%, 100px);) or image URLs to set the wrapping area.

Exclusions make magazine-like layouts on the Web a trivial matter and could spark the kind of creative use of content that we are used to seeing in print!

Grid

Grid properties allow you to throw block-level elements into a grid cell, irrespective of the flow of content within the grid parent element. An element becomes a grid when display is set to grid. You can then set the number of columns and rows with the grid-columns and grid-rows properties, respectively. You can then declare each child selector itself as part of a grid cell, like so:

#title {
grid-column: 1; grid-row: 1;
}
#score {    grid-column: 2; grid-row: 1;
}

You can also use a template to plan the grid:

body {
grid-template: "ta"
"sa"
"bb"
"cc";
}

In this syntax, each string refers to a row, and each character refers to a grid cell. In this case, the content of grid cell represented by the character a spans two rows but just one column, and the content represented by b spans two columns but just one row.

Now you can set any of the child element’s grid-cell position:

#title {
grid-cell: 't';
}

This will make the element with the ID title within the body element to be positioned in the grid cell represented by the character t in the grid-template property.

If you are not using grid-template, you can also declare how many columns or rows a particular element should occupy with the grid-row-span and grid-column-span properties.

Flexbox

Flexbox allows you to distribute child elements anywhere in the box (giving us the much-needed vertical centering), along with flexible units that let you control the fluidity of the child elements’ dimensions.

Note that this specification has changed substantially since it was first proposed. Previously, you would invoke Flexbox for an element with display: box, but now you would use display: Flexbox to do so. Child elements can be vertically aligned to the center with flex-pack: center and horizontally aligned to the center with flex-align: center. Also note that all elements that obey the Flexbox need to be block-level elements.

How Do Various Properties Interact With Each Other?

You might wonder how to use these properties in combination. The following table shows which of these features can be combined.

Paged Media Multiple Columns Regions Exclusions Grid Flexbox
Paged Media
Multiple Columns
Regions
Exclusions
Grid
Flexbox

As you can see, the multiple-column properties can be used in conjunction with generated content for paged media, regions and exclusions. But grid, Flexbox and regions are mutually exclusive (i.e. if an element is a grid, it cannot be a Flexbox or region). Do note that, as Alan Stearns says in the comments, while a grid container cannot be a Flexbox or a region, a grid cell could become a region, or a Flexbox child item could be a region.

A Note Before You Rush Out To Use Them In Client Projects

The specifications are always changing, so be careful with them. Except for multiple columns, I would recommend using these strictly in personal projects and demos. The syntaxes and properties used in some of the demos are different from what you would find in the actual specifications, because they have changed since the builds that support a previous version of the specification came out. Also, because they are still unstable, all of these properties are vendor-prefixed, which means you have to add support for each prefix as support is added.

If you do use these features, just make sure that the content is readable in browsers that do not support them. The easiest way to do this would be to use feature detection and then use CSS to make the content readable when the feature is unsupported.

Help The Working Group!

Do these layout proposals sound exciting to you? Jump on the www-style mailing list to provide feedback on them! Just note that the mailing list will flood your inbox, and you should carefully filter the emails so that you pay attention only to the drafts you are interested in.

Write demos and test how these work, and if you find bugs in the builds that have these properties, provide feedback to the browser vendors and submit bug reports. If you have suggestions for changing or adding properties to these proposals, do write in in the mailing list (or you can bug me on Twitter)!

These are exciting times, and within a few years the way we lay out Web pages will have changed dramatically! Perhaps this will finally sound the death knell of print. (Just kidding.)

 

 

| By: | Posted: December 26, 2011 | PHP Tutorials
phpmaster.com ::

String Handling FunctionsPHP has a vast selection of built-in string handling functions that allow you to easily manipulate strings in almost any possible way. However, learning all these functions, remembering what they do, and when they might come in handy can be a bit daunting, especially for new developers. There is no way I can cover every string function in one article, and besides, that is what the PHP manual is for! But what I will do is show how to work with some of the most commonly used string handling functions that you should know. After this, you’ll be working with strings as well as any concert violinist!

On the Case

PHP offers several functions that enable you to manipulate the case of characters within a string without having to edit the string character by character. Why would you care about this? Well maybe you want to ensure that certain text is all in upper case such as acronyms, titles, for emphasis or just to ensure names are capitalized correctly. Or maybe you just want to compare two strings and you want to ensure the letters you are comparing are the same character set. The case manipulation functions are pretty easy to get to grips with; you just pass the string as a parameter to the function and the return value you is the processed string.

If you wanted to ensure all the letters in a specific string were uppercase, you can use the strtoupper() function as follows:

<?php
$str = "Like a puppet on a string.";
$cased = strtoupper($str);
// Displays: LIKE A PUPPET ON A STRING.
echo $cased;

It is perhaps obvious but still worth noting that numbers and other non-alphabet characters will not be converted.

As you can probably guess, the strtolower() function does the exact opposite of strtoupper() and converts a string into all lowercase letters:

<?php
$str = "LIKE A PUPPET ON A STRING.";
$cased = strtolower($str);
// Displays: like a puppet on a string.
echo $cased;

There may be other times when you want to ensure certain words, such as names or titles, just have the first letter of each word capitalized. For this you can use the ucwords() function:

<?php
$str = "a knot";
$cased = ucwords($str);
// Displays: A Knot
echo $cased;

It is also possible to manipulate the case of just the first letter of a string using the lcfirst() and ucfirst() functions. If you want the first letter to be lowercase, use lcfirst(). If you want the first letter to be uppercase, use ucfirst(). The ucfirst() function is probably the most useful since you can use it to ensure a sentence always starts with a capital letter.

 

A Quick Trim

Sometimes a string needs trimming round the edges. It may have whitespace or other characters at the beginning or end which needs removing. The whitespace can be an actual space character, but it can also be a tab, carriage return, etc. One example of when you might need to do something like this is when you’re working with user input and you want to clean it up it before you start processing it. The trim()function in PHP lets you to do just that; you can pass the string as a parameter and all whitespace from the beginning and end of that string will be removed:

<?php
$str = "  A piece of string?  ";
// Displays: string(22) " A piece of string? "
var_dump($str);

$trimmed = trim($str);
// Displays: string(18) "A piece of string?"
var_dump($trimmed);

trim() is also multi-purpose in that in addition to the string you can also pass it a set of characters and it will remove any that match from the beginning or end:

<?php
$str = "A piece of string?";
$trimmed = trim($str, "A?");
// Displays: string(16) " piece of string"
var_dump($trimmed);

You do need to be careful when you work with these additional characters since trim() will only remove whitespace if you specifically provide it as one of the characters you want removed:

<?php
$str = "A piece of string?";
$trimmed = trim($str, "A ?");
// Displays: string(15) "piece of string"
var_dump($trimmed);

Even though trim() only removes characters at the start and end of a string, it has removed both “A” and the space because when “A” is removed the space becomes the new start of the string, and so that is also removed.

There are also ltrim() and rtrim() functions in PHP which are similar to the trim() function but only remove whitespace (or other specified characters) from the left or right of the string respectively.

How Long is a (Piece of) String?

Very often when working with strings, you’ll want to know how long it is. For example, when dealing with a form, you may have a field where you want to make sure users can’t go over a certain number of characters. To count the number of characters in a string, you can use the strlen() function:

<?php
$str = "How long is a piece of string?";
$size = strlen($str);
// Displays: 30
echo $size;

Cutting Strings Down to Size

Another common situation is finding specific text within a given string and “cutting it” out so you can do something else with it. To cut a string down to size, you need a good pair of scissors, and in PHP your scissors are the substr() function.

To use the substr() function, pass the string you want to work with as a parameter along with a positive or negative integer. The number determines where you’ll start cutting the string; 0 starts you off at the first character of the string (remember that when you count through a string, the first character on the left starts at position 0, not 1).

<?php
$str = "How to cut a string down to size";
$snip = substr($str, 13);
//Displays: string down to size
echo $snip;

When you use a negative number, substr() will start backwards from the end of the string.

<?php
$str = "How to cut a string down to size";
$snip = substr($str, -7);
//Displays: to size
echo $snip;

An optional third parameter to substr() is the length, another integer value that allows you to specify the number of characters you want to extract from the string.

<?php
$str = "How to cut a string down to size";
$snip = substr($str, 13, 6);
//Displays: string
echo $snip;

If you just need to find the position of a particular piece of text within a string and nothing else, you can use the strpos() function which returns the position your selection is from the start of the string. A useful trick, especially when you don’t know the starting position of the text you to cut from a string, is to combine the two functions. Rather than specifying a start position as an integer, you can search for a specific piece of text and then extract that.

<?php
$str = "How to cut a string down to size";
$snip = substr($str, strpos($str, "string"), 6);
//Displays: string
echo $snip;

Swap Shop

Finally, let’s look at replacing a piece of the string with something else, for which you can use str_replace() function. This is ideal for situations where you just want to swap out instances of specific words or a set of characters in a string and replace them with something else:

<?php
$oldstr = "The cat was black";
$newstr = str_replace("black", "white", $oldstr);
// Displays: The cat was white
echo $newstr;

You can also provide arrays to str_replace() if you want to replace multiple values:

<?php
$oldstr  = "The flag was red white and blue.";
$america = array("red", "white", "blue");
$germany = array("black", "red", "yellow");
$newstr = str_replace($america, $germany, $oldstr);
// Displays: The flag was black red and yellow.
echo $newstr;

Summary

Hopefully, this article has given you a taste of some of the things you can do with strings in PHP and made you hungry to learn more. I’ve really barely scraped the tip of the iceberg! The best place to find out more about all of the different string functions is to take some time to read the String Functions page in the PHP Manual.

 

Posted by Maggie on 12/29/2011
filamentgroup.com ::

Progressice EnhancementIn responsive web design, one of the toughest design problems to solve is how format complex tabular data for display on smaller screens. In this post, we’ll explore an experimental approach to rendering a complex table, using progressive enhancement and responsive design methods, that displays comfortably at a wide range of screen sizes, provides quick access to the data, and preserves the table structure so that data can still be compared across columns.

We’ve been batting around the idea of making tables responsive for awhile.

Our initial attempts to make table data palatable on small screens include showing a thumbnail image that links to the data or a canvas-based chart; others have developed responsive CSS workarounds that display a definition list, using either list or table markup. Which approach to take depends on the type of data. For example, structured data where each row is a unique object or entity—say, business contacts, or favorite Netflix movies—are well-suited to a definition list style on small screens, because header and cell data can be displayed as simple label and value pairs (i.e., Name: Maggie Wachs, Company: Filament Group…). The switch to a chart or other visualization on smaller screens works well for a simple numeric comparison of a single value. And snapping down to a thumbnail image that launched a full table to pan and zoom was an okay fallback in lieu of no data at all.

But we encountered a scenario that didn’t quite work with any of the above solutions: a table of complex of financial data with 6-8 related data points, where comparisons and trends among columns are important to see. Visual relationships between headings and cells, and between neighboring columns, are crucial to understanding the data and would be lost on smaller screens if we displayed a list or chart.

We needed a happy medium: a way to keep the basic table structure in place—with headings above, and whole columns that sit side-by-side—and simultaneously display a manageable amount of data at a size that’s comfortably readable.

A table for every screen

The approach we devised starts with a full data set, and uses a simple priority-based class designation to display a manageable subset of data columns for common target screen sizes, and also gives the user control to change column visibility easily.

It’s probably easier to explain with a concrete example: we’ll use a table that lists technology companies and their stock prices and several stock performance metrics. Each row displays data for a single company; columns organize data points by type for comparison. View the demo.

All data columns will display on desktops and tablets in landscape orientation, but only a subset will fit comfortably on anything smaller. So the first order of business is to identify which columns of data are essential to see at all screen widths by default, or optional (shown only when space allows). In our table of tech company stocks, the data is somewhat meaningless without the company name, current stock value, or most recent change, so we’ll consider those essential. The trade time, previous close, and open values would be nice to see if the screen can fit those columns, so we’ll make them optional. The remaining data—bid, ask, and 1-year target estimate—are less important in relative terms, so they will appear on only the widest screens.

In this case, we want users to have the last word regarding which columns to show, so we’ll also create a custom menu that lets them choose which columns to display:

 

The final result is a table that displays a limited set of columns on smaller screens, and provides quick access to data that’s hidden because of space constraints (view the demo). To accomplish this, we’ll use progressive enhancement to ensure that we’re serving a usable experience to all devices. We’ll start with well-formed, semantic table markup and very basic CSS, and then if the browser is capable, apply JavaScript and enhanced CSS (including media queries) to conditionally show a larger number of columns as screen space allows.

Markup

A basic table — with consecutive columns and descriptive headings — is an efficient way to display a complex data set; data arranged into columns and rows are easy to scan and compare. So an HTML table is the clear markup choice for our financial data.

We’ll start with a well-formed table that contains a thead for the heading row, followed by a tbody for the cells.

<table cellspacing="0" id="tech-companies">
<thead>
<tr>
...header cells...
</tr>
</thead>
<tbody>
...rows of data...
</tbody>
</table>

As we fill in the content, we’ll add descriptive classes to identify the essential and optional content. We’ll assign these classes only to the headers; later, we’ll write a little JavaScript to map these headers to their respective columns of data.

<thead>
<tr>
<th>Company</th>
<th>Last Trade</th>
<th>Trade Time</th>
<th>Change</th>
<th>Prev Close</th>
<th>Open</th>
<th>Bid</th>
<th>Ask</th>
<th>1y Target Est</th>
</tr>
...
</thead>

Notice that we added a second class to the Company header, persist. Essential columns are present by default at small screen sizes, but we’ll still be able to toggle their visibility with the custom menu. Marking the Company column with this class provides a way for us to omit it from the menu, and prevent it from being hidden.

We’ll complete the table with rows of data that correspond to the column headers:

<table cellspacing="0" id="tech-companies">
<thead>
...
</thead>
<tbody>
<tr>
<th>GOOG <span>Google Inc.</span></th>
<td>597.74</td>
<td>12:12PM</td>
<td>14.81 (2.54%)</td>
<td>582.93</td>
<td>597.95</td>
<td>597.73 x 100</td>
<td>597.91 x 300</td>
<td>731.10</td>
</tr>
...
</tbody>

Later when we apply JavaScript, we’ll create a custom menu based on the table’s content and append it to the page, immediately above the table. The menu will consist of a container element for a “Display” button and the menu overlay:

<div>
<a href="#">Display</a>
<div>
...menu content...
</div>
</div>

The menu overlay will contain a list of options, one for each column, where each option has a label and checkbox input for toggling that column’s visibility (columns with the persist class will be excluded from the menu):

<div>
<a href="#">Display</a>
<div>
<ul>
<li>
<input type="checkbox" name="toggle-cols" id="toggle-col-1" value="co-1">
<label for="toggle-col-1">Last Trade</label>
</li>
<li>
<input type="checkbox" name="toggle-cols" id="toggle-col-2" value="co-2">
<label for="toggle-col-2">Trade Time</label>
</li>
...
</ul>
</div>
</div>

When the script builds the menu, it will automatically assign name and value attributes and unique IDs to the input elements, and matching for attributes to their labels.

Last but not least, we’ll wrap the table in a container element to simplify positioning the menu:

<div>
<table cellspacing="0" id="tech-companies">
...
</table>
</div>

CSS

We’ll assume you’re already familiar with using CSS3 media queries to render pages responsively. If not, we highly recommend Ethan Marcotte’s definitive article, Responsive Web Design, and book by the same title.

Let’s start with the table. We want it to fill the available space, so we’ll assign a width of 100%:

table {
width: 100%;
font-size: 1.2em;
}

And then apply color, padding, and alignment properties to make the data easier to scan:

thead th {
white-space: nowrap;
border-bottom: 1px solid #ccc;
color: #888;
}
th, td {
padding: .5em 1em;
text-align: right;
}
th:first-child,
td:first-child {
text-align: left;
}
tbody th, td {
border-bottom: 1px solid #e6e6e6;
}

Next, we’ll write the rules that hide and show columns. We’ve scoped these styles to a class, enhanced, which is assigned to the table via JavaScript. This ensures that column visibility is altered only when JavaScript is available. By default, we’ll hide all columns, and show only those marked with the essential class:

.enhanced th,
.enhanced td {
display: none;
}
.enhanced th.essential,
.enhanced td.essential {
display: table-cell;
}

Using CSS3 media queries, we’ll show optional columns when the browser is 500px wide or greater, and all columns at 800px or greater:

@media screen and (min-width: 500px) {
.enhanced th.optional,
.enhanced td.optional {
display: table-cell;
}
}

@media screen and (min-width: 800px) {
.enhanced th,
.enhanced td {
display: table-cell;
}
}

When using this approach, how you prioritize and categorize your data must correspond to the number of screen size breakpoints you plan to support. In our example, we’ve chosen to have two breakpoints, at 500 and 800 pixels wide, and two levels of importance, essential and optional. If we were to add another break point, say around 400px, we would need to rework our categories to include a third (i.e., primary, secondary, tertiary) so that we can mark each column to be visible at a particular breakpoint.

When the custom menu is inserted into the table’s container, it will appear just above the table on the right:

.table-menu-wrapper {
position: absolute;
top: -3em;
right: 0;
}

The menu itself will also be absolutely positioned, and by default will be hidden with the table-menu-hidden class (later, we’ll write JavaScript to toggle that class when the “Display” button is clicked):

.table-menu {
position: absolute;
right: 0;
left: auto;
background-color: #fff;
padding: 10px;
border: 1px solid #ccc;
font-size: 1.2em;
width: 12em;
}
.table-menu-hidden {
left: -999em;
right: auto;
}

Finally, we’ll add relative positioning to the table’s container. Later, when we append the menu we can position it without having to calculate location coordinates:

.table-wrapper {
position: relative;
margin: 5em 5%;
}

JavaScript

The table we just created is usable on its own; any browser that renders HTML will display it. With a few JavaScript enhancements, we’ll be able to view the table at smaller screen sizes without sacrificing the table structure. (The following examples use jQuery.)

First we’ll append the enhanced class for scoping styles:

// add class for scoping styles - cells should be hidden only when JS is on
table.addClass("enhanced");

We’ll create a container element for the menu, which will come into play a little later in the script:

var container = $('<div class="table-menu table-menu-hidden"><ul /></div>'); 

Then we’ll enhance the markup with classes and attributes that allow us to control column visibility. We’ll loop through the table headers and assign them unique IDs, then reference those IDs in headers attributes assigned to associated cells. (The headers attribute identifies to which header(s) a cell belongs.) We’ll also copy the classes that we assigned to the column headers — essential and optional — and assign them to the associated columns.

$( "thead th" ).each(function(i){
var th = $(this),
id = th.attr("id"),
classes = th.attr("class");  // essential, optional (or other content identifiers)

// assign an ID to each header, if none is in the markup
if (!id) {
id = ( "col-" ) + i;
th.attr("id", id);
};

// loop through each row to assign a "headers" attribute and any classes (essential, optional) to the matching cell
// the "headers" attribute value = the header's ID
$( "tbody tr" ).each(function(){
var cell = $(this).find("th, td").eq(i);
cell.attr("headers", id);
if (classes) { cell.addClass(classes); };
});
...

Next, while still looping through the headers, we’ll create a menu item for each column, except for those marked with the persist class. Each menu item consists of a checkbox and label with the column header text.

...
// create the menu hide/show toggles
if ( !th.is(".persist") ) {

// note that each input's value matches the header's ID;
// later we'll use this value to control the visibility of that header and it's associated cells
var toggle = $('<li><input type="checkbox" name="toggle-cols" id="toggle-col-'+i+'" value="'+id+'" /> <label for="toggle-col-'+i+'">'+th.text()+'</label></li>');

// append each toggle to the container
container.find("ul").append(toggle);

...

And then we’ll bind events to each checkbox for controlling that column’s visibility.

...

// assign behavior
toggle.find("input")

// when the checkbox is toggled
.change(function(){
var input = $(this),
val = input.val(),  // this equals the header's ID, i.e. "company"
cols = $("#" + val + ", [headers="+ val +"]"); // so we can easily find the matching header (id="company") and cells (headers="company")

if (input.is(":checked")) { cols.show(); }
else { cols.hide(); };
})

// custom event that sets the checked state for each toggle based on column visibility, which is controlled by @media rules in the CSS
// called whenever the window is resized or reoriented (mobile)
.bind("updateCheck", function(){
if ( th.css("display") ==  "table-cell") {
$(this).attr("checked", true);
}
else {
$(this).attr("checked", false);
};
})

// call the custom event on load
.trigger("updateCheck");

}; // end conditional statement ( !th.is(".persist") )
}); // end headers loop

After closing the headers loop, we’ll bind our custom event to the window’s resize and orientation change events:

// update the inputs' checked status
$(window).bind("orientationchange resize", function(){
container.find("input").trigger("updateCheck");
});

And, last but not least, append our checkbox menu to the page and bind show/hide menu events:

var menuWrapper = $('<div />'),
menuBtn = $('<a href="#">Display</a>');

menuBtn.click(function(){
container.toggleClass("table-menu-hidden");
return false;
});

menuWrapper.append(menuBtn).append(container);
table.before(menuWrapper);  // append the menu immediately before the table

// assign click-away-to-close event
$(document).click(function(e){
if ( !$(e.target).is( container ) && !$(e.target).is( container.find("*") ) ) {
container.addClass("table-menu-hidden");
}
});

Media query support for IE: Respond.js

Older versions of IE (8 and earlier) don’t natively support CSS3 media queries, so we need to use a workaround in those browsers to implement our responsive table. Thanks to our own Scott Jehl, we can use a lightweight polyfill script, respond.js, that enables support for min- and max-width media query properties. The script is open source and available on github.

Keep the conversation going

The pattern discussed here is one possibility for coding a responsive table. We hope to discover more, and will update our RWD-Table-Patterns git repository as we come across additional use cases.

The demo code shown here is open source and available for download. Feel free to put it through its paces. If you use it and see room for improvement, please submit a pull request and we’ll review it as soon as possible.

 

 

By | October 27, 2011 |
sitepoint.com ::

Scaling, skewing and rotating any element is possible with the CSS3 transform property. It’s supported in all modern browsers (with vendor prefixes) and degrades gracefully, e.g.

#myelement
{
-webkit-transform: rotate(30deg);
-moz-transform: rotate(30deg);
-ms-transform: rotate(30deg);
-o-transform: rotate(30deg);
transform: rotate(30deg);
}

Great stuff. However, this rotates the whole element — it’s content, border and background image. What if you only want to rotate the background image? Or what if you want the background to remain fixed while the element is rotated?

Currently, there’s no W3C proposal for background-image transformations. It would be incredibly useful so I suspect one will appear eventually, but that doesn’t help developers who want to use similar effects today.

Fortunately, there is a solution. In essence, it’s a hack which applies the background image to a before or after pseudo element rather than the parent container. The pseudo element can then be transformed independently.

Transforming the Background Only

The container element can have any styles applied but it must be set to position: relative since our pseudo element will be positioned within it. You should also set overflow: hidden unless you’re happy for the background to spill out beyond the container.

#myelement
{
position: relative;
overflow: hidden;
}

We can now create an absolutely-positioned pseudo element with a transformed background. The z-index is set -1 to ensure it appears below the container’s content.

#myelement:before
{
content: "";
position: absolute;
width: 200%;
height: 200%;
top: -50%;
left: -50%;
z-index: -1;
background: url(background.png) 0 0 repeat;
-webkit-transform: rotate(30deg);
-moz-transform: rotate(30deg);
-ms-transform: rotate(30deg);
-o-transform: rotate(30deg);
transform: rotate(30deg);
}

Note you may need to adjust the pseudo element’s width, height and position. For example, if you’re using a repeated image, a rotated area must be larger than its container to fully cover the background:

transform background

Fixing the Background on a Transformed Element

All transforms on the parent container are applied to pseudo elements. Therefore, we need to undo that transformation, e.g. if the container is rotated by 30 degrees, the background must be rotated -30 degrees to return to a fixed position:

#myelement
{
position: relative;
overflow: hidden;
-webkit-transform: rotate(30deg);
-moz-transform: rotate(30deg);
-ms-transform: rotate(30deg);
-o-transform: rotate(30deg);
transform: rotate(30deg);
}
#myelement:before
{
content: "";
position: absolute;
width: 200%;
height: 200%;
top: -50%;
left: -50%;
z-index: -1;
background: url(background.png) 0 0 repeat;
-webkit-transform: rotate(-30deg);
-moz-transform: rotate(-30deg);
-ms-transform: rotate(-30deg);
-o-transform: rotate(-30deg);
transform: rotate(-30deg);
}

Again, you will need to adjust the size and position to ensure the background covers the parent container adequately.

Please view the demonstration page for examples. The full code is contained in the HTML source.

The effects work in IE9, Firefox, Chrome, Safari and Opera. IE8 will not show any transformations but the background appears.

IE6 and 7 do not support pseudo elements so the background disappears. However, if you want to support those browsers, you could apply a background image to the container then set it to “none” using an advanced selector or conditional CSS.

Full code contained in the HTML source:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Background Image Transformations</title>
<style>
body
{
	font-family: arial, helvetica, freesans, sans-serif;
	font-size: 100%;
	color: #333;
	background-color: #ddd;
}

h1
{
	font-size: 1.5em;
	font-weight: normal;
	margin: 0;
}

#element0, #element1, #element2, #element3
{
	width: 12em;
	font-size: 2em;
	text-align: center;
	line-height: 5em;
	margin: 3em auto;
	border: 2px solid #666;
	border-radius: 7px;
}

#element0, #element1
{
	background: url(background.png) 0 0 repeat;
}

#element1, #element3
{
	-webkit-transform: rotate(30deg);
	-moz-transform: rotate(30deg);
	-ms-transform: rotate(30deg);
	-o-transform: rotate(30deg);
	transform: rotate(30deg);
}

#element2, #element3
{
	position: relative;
	overflow: hidden;
}

#element2:before, #element3:before
{
	content: "";
	position: absolute;
	width: 200%;
	height: 200%;
	top: -50%;
	left: -50%;
	z-index: -1;
	background: url(background.png) 0 0 repeat;
}

#element2:before
{
	-webkit-transform: rotate(30deg);
	-moz-transform: rotate(30deg);
	-ms-transform: rotate(30deg);
	-o-transform: rotate(30deg);
	transform: rotate(30deg);
}

#element3:before
{
	-webkit-transform: rotate(-30deg);
	-moz-transform: rotate(-30deg);
	-ms-transform: rotate(-30deg);
	-o-transform: rotate(-30deg);
	transform: rotate(-30deg);
}
</style>

</head>
<body>

<h1>Background Image Transformations</h1>

<div id="element0">No Transformation</div>
<div id="element1">Transformed Element</div>

<div id="element2">Transformed Background</div>

<div id="element3">Fixed Background</div>

<p>For more information, please please refer to:<br />
<a href="http://blogs.sitepoint.com/css3-transform-background-image/">How to Apply CSS3 Transformations to Background Images</a></p>

<p>This example code was developed by <a href="http://twitter.com/craigbuckler">Craig Buckler</a> of <a href="http://optimalworks.net/">OptimalWorks.net</a> for <a href="http://sitepoint.com/">SitePoint.com</a>.</p>
<p>It can be used without any restrictions but please don't expect 24/7 support! A link back to <a href="http://www.sitepoint.com/">SitePoint.com</a> is appreciated.</p>

</body>
</html>