Rearrange content when it’s too wide with jQuery

From its humble beginnings more than 25 years ago to the omnipresent behemoth it is today, the web has always been changing. Recently, the explosion in the popularity of mobiles and tablets has left web designers struggling to make their layouts adaptable to as many screen sizes and resolutions as possible. Today, I’ll show another way that will allow you to modify the layout depending on how much space is available.

We’ll be building a simple website header with the site’s title and a navigation menu. Depending on how much space is available in the header, the title and the navigation will be restyled.

1. HTML

The HTML for the page we’re going to build is quite simple: a main container to hold all the content, a title, and the navigation.

<section id="main">

	<h1 id="title">Website Title</h1>

	<nav>
		<ul id="navigation">

		</ul>
	</nav>

</section>

Here’s where the fun part comes in: you can put however many menu items you want into the navigation. For the sake of the tutorial, let’s use these four:

<ul id="navigation">
	<li><a href="#">Home</a></li>
	<li><a href="#">About Us</a></li>
	<li><a href="#">Contact</a></li>
	<li><a href="#">Portfolio</a></li>	
</ul>

That’s all we need for the HTML.

2. CSS

We’ll make this layout clean and simple: A white box floating on top of a subtle grey background.

body {
background: url('bg.png');
font-family: Times new roman;
color: #666;
}

You can download the “bg.png” image here, or you can just have a grey background such as “#eee“. The font-family is Times New Roman, and the color is a dark grey.

Now, we’ll need to style the main container:

#main {
width: 70%;
padding: 25px;
margin: 0 auto;
margin-top: 100px;
background: #fff;
border: 1px solid #cacaca;
}

This may seem like a lot to take in, but it is quite simple. We’re giving the “#main” element a percentage width so that it changes width depending on the browser size. It will also have some padding to distance the elements inside from the border, and we’ll center it by telling it to have a margin of “0 auto”. Then, we distance it from the top of the page by 100px. The background is white, and it has a light grey border.

Since we’ll be floating the elements inside, we need to have a clearfix. However, this is 2012; we’re not going to use a whole separate element for the clearfix! We’ll use Chris Coyier’s technique to clear the elements inside.

#main:before,
#main:after {
    content:"";
    display:table;
}
#main:after {
    clear:both;
}
#main {
    zoom:1; /* For IE 6/7 (trigger hasLayout) */
} 

This way, the “#main” element stretches to fit around the elements inside.

Now, we need to style the rest of the elements inside:

#main h1 {
font-size: 32px;
float: left;	
}

#main nav {
float: right;
font-size: 16px;
}

Notice the fact that the title and the navigation are floated to opposite sides so that they stay out of each other’s way.

The links inside the menu still need some work, though.

ul#navigation li {
display:inline-block;
line-height: 32px;
margin-left: 10px;	
}

ul#navigation li a:hover {
color: #888;
}

That’s all the CSS we need for the bigger-screen variants of the navigation and the title. There’s one thing left though: the CSS for the smaller-screen variants.

h1.smallTitle {
font-size: 40px;
width: 100%;
text-align: center;
}

nav.smallNav {
margin-top: 5px;
font-size: 17px;
width: 100%;
text-align: center;
}

We’ve made the text larger, and centered the two things.

That’s it for the CSS necessary.

3. Javascript

In HTML5, it is not against coding standards to use attributes beginning with “data-“. These can be used to store data about an element. In our case, we’ll use this type of attribute to store the original width of the two elements.

[js]
$(document).ready(function(){

var titleWidth = $(‘#title’).width();
$(‘#title’).attr(‘data-orig’,titleWidth);
var navWidth = $(‘nav’).width();
$(‘nav’).attr(‘data-orig’,navWidth);

});
[/js]

Here, we’re taking the widths of the title and the nav, and storing them inside “data-orig” attributes inside the two elements.

Now, we need to create a function that will check to see if the two elements fit inside the parent container, and apply the necessary code depending on the situation.

[js]
$(document).ready(function(){

var titleWidth = $(‘#title’).width();
$(‘#title’).attr(‘data-orig’,titleWidth);
var navWidth = $(‘nav’).width();
$(‘nav’).attr(‘data-orig’,navWidth);

function navRearrange(){
var containerWidth = $(‘#main’).width() – 20;
var origTitleWidth = parseInt($(‘#title’).attr(‘data-orig’));
var origNavWidth = parseInt($(‘nav’).attr(‘data-orig’));
}
});

[/js]

Inside this function, we’re defining three variables: containerWidth, origTitleWidth, and origNavWidth. We need these variables so that we can later on add the navigation width and the title width to see if it is greater than the container width. In this case, we’re subtracting 20 from the main container width so that the two elements are switched to the smaller-screen versions of themselves when they are 20 pixels apart, not when they are right next to each other.

Now, you might ask, “Why do I need to store the width in this “data-orig” attribute? Why can’t I just take the width of the element?” Take a look at the CSS classes we defined for the small versions of these two elements. Notice the fact that we’re giving them “100%” widths. If we take the widths of the elements after they are changed to the smaller versions of themselves, the widths will be completely different from the original widths of the elements. With the “data-orig” attributes, we’re always working with the real width of the elements.

Since we have all the necessary variables defined, it’s time to write the code that will apply the proper styles to the elements.

[js]
function navRearrange(){
var containerWidth = $(‘#main’).width() – 20;
var origTitleWidth = parseInt($(‘#title’).attr(‘data-orig’));
var origNavWidth = parseInt($(‘nav’).attr(‘data-orig’));

if(origNavWidth+origTitleWidth>=containerWidth){
$(‘#title’).addClass(‘smallTitle’);
$(‘nav’).addClass(‘smallNav’);
}
else{
$(‘#title’).removeClass(‘smallTitle’);
$(‘nav’).removeClass(‘smallNav’);
}
}
[/js]

We’re doing this with the help of an “if…else” statement. If the “if” statement is true, the code inside it gets applied. If it isn’t true, the code inside the “else” part gets applied. All we’re doing is adding or removing the “small” classes, depending on whether or not the two elements fit inside the parent container.

Since this is a function, we need to call it:

[js]
function navRearrange(){
var containerWidth = $(‘#main’).width() – 20;
var origTitleWidth = parseInt($(‘#title’).attr(‘data-orig’));
var origNavWidth = parseInt($(‘nav’).attr(‘data-orig’));

if(origNavWidth+origTitleWidth>=containerWidth){
$(‘#title’).addClass(‘smallTitle’);
$(‘nav’).addClass(‘smallNav’);
}
else{
$(‘#title’).removeClass(‘smallTitle’);
$(‘nav’).removeClass(‘smallNav’);
}
}

navRearrange();

[/js]

When the page loads, this function will fire. But what if the page is resized?

[js]
$(window).resize(function(){
navRearrange();
});
[/js]

If the window is resized, this function fires.

Here’s all the Javascript code:

[js]
$(document).ready(function(){

var titleWidth = $(‘#title’).width();
$(‘#title’).attr(‘data-orig’,titleWidth);
var navWidth = $(‘nav’).width();
$(‘nav’).attr(‘data-orig’,navWidth);

function navRearrange(){
var containerWidth = $(‘#main’).width() – 20;
var origTitleWidth = parseInt($(‘#title’).attr(‘data-orig’));
var origNavWidth = parseInt($(‘nav’).attr(‘data-orig’));

if(origNavWidth+origTitleWidth>=containerWidth){
$(‘#title’).addClass(‘smallTitle’);
$(‘nav’).addClass(‘smallNav’);
}
else{
$(‘#title’).removeClass(‘smallTitle’);
$(‘nav’).removeClass(‘smallNav’);
}

}

navRearrange();

$(window).resize(function(){
navRearrange();
});

});
[/js]

That’s it. Hopefully, this tutorial taught you how to make your layouts even more adaptable to different screen sizes. This method is particularly useful for WordPress themes with custom menus, as you never know how many links will be inside the menu.

If you have any questions or comments, feel free to comment below.

Author: (8 Posts)

Alexandre Smirnov is a web developer and designer who lives and works in California. He enjoys creating cool new stuff out of CSS3 and HTML5, and is convinced that Jquery is the meaning of life. He also regularly writes on his blog, DesignLunatic.com.

Comments