Menu icon Foundation
Adaptive Layouts in Foundation 6 (SOLUTION)

Quicktro
For once I thought it was high time to post something useful rather than just asking questions, so here's my first (hopefully) useful post.

This post assumes you are using a build system and SCSS. 

Introduction
When it comes to mobile first support there are two opposing schools, Responsive and Adaptive - they should not be opposing, but often are. The Foundation framework out of the box discusses its responsive pedigree, but quietly recognises at very large screen sizes adaptive may be more appropriate. Consider the "large" breakpoint, which dutifully sets the content size to a fixed width when the browser width is more than 1024 pixels. Of course, you can override this by adding "expand" to the row, but for the most part developers using Foundation appear to leave this alone.

The latest (version 3+) Bootstrap and most other frameworks take a different approach, with many fixed widths above a certain browser window width, keeping responsive layouts for tablets and other limited screen size devices.

I don't think anyone is going to decry the benefits of a responsive approach to design on tablets and phones, but for larger devices responsive only design can make pages unwieldy and is often quite inappropriate. I expect a lot of responsive zealots are screaming right now - in their tablet world such religious fervour can be warranted. Even on larger screens, responsive can be the right way to go; that's why Zurb included "expand", to disable the large screen adaptive fixed width.

For dashboards and similar kinds of pages, adaptive design for large screens makes for clearer pages and a better user experience. In these particular cases, the compromises of responsive design are not acceptable to most users. If at this point you are saying "well, the user should just use a smaller browser window" you've missed the point entirely.

This post is therefore about adding adaptive breakpoints to Foundation without breaking the underlying responsive functionality. In the end this was quite simple, but it did require the tiniest amount of "off-the-grid" thinking, so to speak.

A numerical values used in the following solution are for you to change as you see fit - they work for me and countless sites, but that is not to say they will suit you. Hack them as you wish, the solution still works as intended.

The Adaptive Grid Solution - Part 1: Adjusting Breakpoints

The first part of the solution has nothing at all to do with adaptive breakpoints, but breakpoints in general. I have never been very happy with Zurb's choice of what it considers a "small" or "medium" screen. The widths always seemed to be for devices which did not exist in the wild. So I took the view that "small" was for anything considered a low-res phone or tablet and "medium" any kind of current tablet. Looking at many tablets and phones it was clear to see a phone was anything with a logical width of 768px or fewer and a tablet anything with a logical width of 1024px or fewer. There are of course many tablets with many more physical pixels than this, but the logical pixels adhered to this convention. As a result, I always make the following change to my "_settings.scss" file.

// 2. Breakpoints
// --------------

$breakpoints: (
  small: 0,
  medium: 768px,
  large: 1025px,
  xlarge: 1170px,
  xxlarge: 1440px,
  xxxlarge: 1920px,
);
$breakpoint-classes: (small medium large xlarge xxlarge xxxlarge);

You will notice I added "xxlarge" and "xxxlarge" by way of illustrating how you can add very large screen size adaptive breakpoints to Foundation. You do not even have to use the "xxxlarge" type name, you can call the breakpoint "henry" if you like, it still works. You could have "show-for-henry-only" as a visibility condition - Foundation is pretty cool that way. However, do not rename the common names like "small", "medium", "large" and so on - those names are relied upon in the framework!

If you do add more breakpoints or if you change the maximum width of the final breakpoint, you you MUST change the $global-width SCSS variable in "_settings.scss" to match. In my case the change would be:

$global-width: rem-calc(1920);

What we have now is a framework which performs in a responsive manner all the way up to 1920px, at which point the built in adaptive breakpoint provided by Foundation kicks in by having a maximum content width of 1920px.

If you don't want to go that high, just drop all the larger sizes and adjust the $global-width accordingly.

e.g. For just the default breaks of "small", "medium", and "large" you can do the following:

$global-width: rem-calc(1025);

...

$breakpoints: (
  small: 0,
  medium: 768px,
  large: 1025px
);
$breakpoint-classes: (small medium large);

For my projects, these changes result in "small" catering to small tablets and phones, "medium" working for common midsize and larger tablets, and "large" for desktop. I frequently do use "xlarge" and "xxlarge" for very big dashboards. The numbers I present here are good for Apple i-thingies - so that should please much of the audience ;-)

The Adaptive Grid Solution - Part 2: 

Now the tricky bit: making rows adaptive at several breakpoints rather than the one provided by Foundation. Hacking on the "row" class quickly taught me it's not as independent of the rest of the framework as you may think. Remember, rows contain columns which can contain rows which can contain columns as so on ad-infinitum. If we set rules for the "row" class, all seems well until we get to very large screens, at which point the hacks break down. Add flex-grid into the mix and we're heading for very rocky shores indeed. Further, as the update from version 6.2 to 6.2.1 taught me, my hacks were "fragile" when the framework was updated. 

The solution to all of this was actually quite simple. I'm not a fan of adding CSS conditionals to classes just because I can. Indeed, I could have set some rules which told the browser "only apply this style if the row is the first one," but such complexity *may* introduce fragility. It would look cool to other geeks, I would have bragging rights for my "l33t-skillz", but Zurb could easy change something and break my hack with a single line of code - and who would I be to argue against their choice for their own framework - nobody, that's who.

Instead, I went for a simple solution which is not "hacky" at all. I created a new class which sits in my "app.scss" or similar. I call it ".arow" - that's "Adaptive Row." FYI: I say it "arrow" - please do let me have this one little conceit :-)
So, here it is expanded to a longhand form for clarity... (*Don't do it this way - illustration purposes only!)

/* Longhand method - don't do it this way */

@media screen and (min-width: 0px) and (max-width: 1024px)
{
	.arow { width: 100%; }
}

@media screen and (min-width: 1025px) and (max-width: 1169px)
{
	.arow { width: 1025px; }
}

@media screen and (min-width: 1170px) and (max-width: 1439px)
{
	.arow { width: 1170px; }
}

@media screen and (min-width: 1440px) and (max-width: 1919px)
{
	.arow { width: 1440px; }
}

@media screen and (min-width: 1920px)
{
	.arow { width: 1920px; }
}

There is a better way to write this code all inside a single ".arow" definition, but I have separated it out for ease of understanding. If you are not using xlarge and bigger sizes, you should drop the lines with "1170px" and above and remove "max-width" from the final condition.

However, it's better to leverage F6 when creating the ".arow" class - better to do it the following way.

/* Do it this way! */
.arow
{
	width:100%;

	@include breakpoint(large) { width: 1025px; }
	@include breakpoint(xlarge) { width: 1170px; }
	@include breakpoint(xxlarge) { width: 1440px; }
	@include breakpoint(xxxlarge) { width: 1920px; }
}


What it is doing is keeping the width as responsive for "small" and "medium" widths and setting a number of fixed widths for larger screen widths. It does not need auto margins - the Foundation framework already takes care of that.
Using it is simplicity itself:

<div class="row arow">
	<div class="small-6 column">
		<div class="row">
			<div class="small-6 column">
				Some content
			</div>
			<div class="small-6 column">
				Some content
			</div>
		</div>
	</div>
	<div class="small-6 column">
		<div class="row">
			<div class="small-6 column">
				Some content
			</div>
			<div class="small-6 column">
				Some content
			</div>
		</div>
	</div>
</div>

The above is an example with nested rows, just to illustrate how that's done. If there is anything unclear, it's likely you need to go back to the Foundation documentation. It even works with Flex-grid. Here's the same example with "shrink" and "expand"

<div class="row arow">
	<div class="shrink column">
		<div class="row">
			<div class="small-6 column">
				Some content
			</div>
			<div class="small-6 column">
				Some content
			</div>
		</div>
	</div>
	<div class="column">
		<div class="row">
			<div class="column">
				Some content
			</div>
			<div class="shrink column">
				Some content
			</div>
		</div>
	</div>
</div>


Enjoy your new adaptive breakpoints. Hopefully, this will bring a few more people over from Bootstrap.

Adaptive breakpointsAdaptive vs ResponsiveResponsive

Quicktro
For once I thought it was high time to post something useful rather than just asking questions, so here's my first (hopefully) useful post.

This post assumes you are using a build system and SCSS. 

Introduction
When it comes to mobile first support there are two opposing schools, Responsive and Adaptive - they should not be opposing, but often are. The Foundation framework out of the box discusses its responsive pedigree, but quietly recognises at very large screen sizes adaptive may be more appropriate. Consider the "large" breakpoint, which dutifully sets the content size to a fixed width when the browser width is more than 1024 pixels. Of course, you can override this by adding "expand" to the row, but for the most part developers using Foundation appear to leave this alone.

The latest (version 3+) Bootstrap and most other frameworks take a different approach, with many fixed widths above a certain browser window width, keeping responsive layouts for tablets and other limited screen size devices.

I don't think anyone is going to decry the benefits of a responsive approach to design on tablets and phones, but for larger devices responsive only design can make pages unwieldy and is often quite inappropriate. I expect a lot of responsive zealots are screaming right now - in their tablet world such religious fervour can be warranted. Even on larger screens, responsive can be the right way to go; that's why Zurb included "expand", to disable the large screen adaptive fixed width.

For dashboards and similar kinds of pages, adaptive design for large screens makes for clearer pages and a better user experience. In these particular cases, the compromises of responsive design are not acceptable to most users. If at this point you are saying "well, the user should just use a smaller browser window" you've missed the point entirely.

This post is therefore about adding adaptive breakpoints to Foundation without breaking the underlying responsive functionality. In the end this was quite simple, but it did require the tiniest amount of "off-the-grid" thinking, so to speak.

A numerical values used in the following solution are for you to change as you see fit - they work for me and countless sites, but that is not to say they will suit you. Hack them as you wish, the solution still works as intended.

The Adaptive Grid Solution - Part 1: Adjusting Breakpoints

The first part of the solution has nothing at all to do with adaptive breakpoints, but breakpoints in general. I have never been very happy with Zurb's choice of what it considers a "small" or "medium" screen. The widths always seemed to be for devices which did not exist in the wild. So I took the view that "small" was for anything considered a low-res phone or tablet and "medium" any kind of current tablet. Looking at many tablets and phones it was clear to see a phone was anything with a logical width of 768px or fewer and a tablet anything with a logical width of 1024px or fewer. There are of course many tablets with many more physical pixels than this, but the logical pixels adhered to this convention. As a result, I always make the following change to my "_settings.scss" file.

// 2. Breakpoints
// --------------

$breakpoints: (
  small: 0,
  medium: 768px,
  large: 1025px,
  xlarge: 1170px,
  xxlarge: 1440px,
  xxxlarge: 1920px,
);
$breakpoint-classes: (small medium large xlarge xxlarge xxxlarge);

You will notice I added "xxlarge" and "xxxlarge" by way of illustrating how you can add very large screen size adaptive breakpoints to Foundation. You do not even have to use the "xxxlarge" type name, you can call the breakpoint "henry" if you like, it still works. You could have "show-for-henry-only" as a visibility condition - Foundation is pretty cool that way. However, do not rename the common names like "small", "medium", "large" and so on - those names are relied upon in the framework!

If you do add more breakpoints or if you change the maximum width of the final breakpoint, you you MUST change the $global-width SCSS variable in "_settings.scss" to match. In my case the change would be:

$global-width: rem-calc(1920);

What we have now is a framework which performs in a responsive manner all the way up to 1920px, at which point the built in adaptive breakpoint provided by Foundation kicks in by having a maximum content width of 1920px.

If you don't want to go that high, just drop all the larger sizes and adjust the $global-width accordingly.

e.g. For just the default breaks of "small", "medium", and "large" you can do the following:

$global-width: rem-calc(1025);

...

$breakpoints: (
  small: 0,
  medium: 768px,
  large: 1025px
);
$breakpoint-classes: (small medium large);

For my projects, these changes result in "small" catering to small tablets and phones, "medium" working for common midsize and larger tablets, and "large" for desktop. I frequently do use "xlarge" and "xxlarge" for very big dashboards. The numbers I present here are good for Apple i-thingies - so that should please much of the audience ;-)

The Adaptive Grid Solution - Part 2: 

Now the tricky bit: making rows adaptive at several breakpoints rather than the one provided by Foundation. Hacking on the "row" class quickly taught me it's not as independent of the rest of the framework as you may think. Remember, rows contain columns which can contain rows which can contain columns as so on ad-infinitum. If we set rules for the "row" class, all seems well until we get to very large screens, at which point the hacks break down. Add flex-grid into the mix and we're heading for very rocky shores indeed. Further, as the update from version 6.2 to 6.2.1 taught me, my hacks were "fragile" when the framework was updated. 

The solution to all of this was actually quite simple. I'm not a fan of adding CSS conditionals to classes just because I can. Indeed, I could have set some rules which told the browser "only apply this style if the row is the first one," but such complexity *may* introduce fragility. It would look cool to other geeks, I would have bragging rights for my "l33t-skillz", but Zurb could easy change something and break my hack with a single line of code - and who would I be to argue against their choice for their own framework - nobody, that's who.

Instead, I went for a simple solution which is not "hacky" at all. I created a new class which sits in my "app.scss" or similar. I call it ".arow" - that's "Adaptive Row." FYI: I say it "arrow" - please do let me have this one little conceit :-)
So, here it is expanded to a longhand form for clarity... (*Don't do it this way - illustration purposes only!)

/* Longhand method - don't do it this way */

@media screen and (min-width: 0px) and (max-width: 1024px)
{
	.arow { width: 100%; }
}

@media screen and (min-width: 1025px) and (max-width: 1169px)
{
	.arow { width: 1025px; }
}

@media screen and (min-width: 1170px) and (max-width: 1439px)
{
	.arow { width: 1170px; }
}

@media screen and (min-width: 1440px) and (max-width: 1919px)
{
	.arow { width: 1440px; }
}

@media screen and (min-width: 1920px)
{
	.arow { width: 1920px; }
}

There is a better way to write this code all inside a single ".arow" definition, but I have separated it out for ease of understanding. If you are not using xlarge and bigger sizes, you should drop the lines with "1170px" and above and remove "max-width" from the final condition.

However, it's better to leverage F6 when creating the ".arow" class - better to do it the following way.

/* Do it this way! */
.arow
{
	width:100%;

	@include breakpoint(large) { width: 1025px; }
	@include breakpoint(xlarge) { width: 1170px; }
	@include breakpoint(xxlarge) { width: 1440px; }
	@include breakpoint(xxxlarge) { width: 1920px; }
}


What it is doing is keeping the width as responsive for "small" and "medium" widths and setting a number of fixed widths for larger screen widths. It does not need auto margins - the Foundation framework already takes care of that.
Using it is simplicity itself:

<div class="row arow">
	<div class="small-6 column">
		<div class="row">
			<div class="small-6 column">
				Some content
			</div>
			<div class="small-6 column">
				Some content
			</div>
		</div>
	</div>
	<div class="small-6 column">
		<div class="row">
			<div class="small-6 column">
				Some content
			</div>
			<div class="small-6 column">
				Some content
			</div>
		</div>
	</div>
</div>

The above is an example with nested rows, just to illustrate how that's done. If there is anything unclear, it's likely you need to go back to the Foundation documentation. It even works with Flex-grid. Here's the same example with "shrink" and "expand"

<div class="row arow">
	<div class="shrink column">
		<div class="row">
			<div class="small-6 column">
				Some content
			</div>
			<div class="small-6 column">
				Some content
			</div>
		</div>
	</div>
	<div class="column">
		<div class="row">
			<div class="column">
				Some content
			</div>
			<div class="shrink column">
				Some content
			</div>
		</div>
	</div>
</div>


Enjoy your new adaptive breakpoints. Hopefully, this will bring a few more people over from Bootstrap.

Rafi Benkual over 3 years ago

Wow! Great write up!

A couple thoughts on this:

- There might be a way to pull the largest value in the breakpoint map into the global width, say if you set a variable to true. Something like 

$fluid-grid: true;

- I think that this information could be good in the docs, or as a guest Blog post on the ZURB blog.

- Instead of hand writing out the row width for each breakpoint, this may be a great setting to also have in a Sass map.

- I wouldn't argue between responsive or adaptive but rather what works better for a specific use case. If the Foundation Sass can make this more accessible, and there are great writ ups like you have done on it, it would be worth putting forth.

 

Brandon Arnold about 3 years ago

Awesome, man!