zurb / foundation-apps

The first front-end framework created for developing fully responsive web apps.
http://foundation.zurb.com/apps
MIT License
1.58k stars 216 forks source link

Feedback on grid structure and classes #36

Closed gakimball closed 9 years ago

gakimball commented 9 years ago

The Grid

In this thread we'd like to get your feedback on the Foundation for Apps grid. We're very excited about the grid, as it's going to allow developers to highly flexible, responsive app layouts that just aren't possible with the CSS floats of yore.

The grid code can be found in this file: scss/components/_grid.scss.

The grid is very close to feature-complete, and includes these features:

To start off, our decision to use Flexbox is pretty much set in stone. We've heard some concerns from the community regarding browser support, which we totally get. We've made the choice to be somewhat bleeding-edge, but this is also something of a long game. We at ZURB think web apps will only become more prominent, and this framework is meant to make web apps more powerful, and easier to develop.

Globally, some form of Flexbox support exists in over 80% of web browsers in use worldwide. To recap, we have totally solid support in:

Support gets a little shaky with iOS 6, Safari 6, and Android 2—4.3, which don't support wrapping of flex items. And support doesn't exist at all in Internet Explorer 9.

The grid syntax

Originally the grid had two core concepts: the "group" and "block". These were roughly analagous to rows and columns in other grid systems, where the former is for layout and the latter is for content. A basic grid might look like:

<div class="group">
  <div class="small-4 block"></div>
  <div class="small-8 block"></div>
</div>

However, because of the... flexibility of Flexbox, groups can be nested immediately inside groups, and be given sizing or ordering classes, just like blocks.

<div class="group" id="container">
  <!-- A fixed title bar and a scrolling pane of content -->
  <div class="vertical large-4 group" id="sidebar">
    <div class="shrink block" id="sidebarTitle"></div>
    <div class="block" id="sidebarContent"></div>
  </div>
  <!-- The main content area -->
  <div class="large-8 block" id="main"></div>
</div>

As you can see, not only are we immediately nesting groups inside groups (contrast this with Foundation 5, wherein you aren't supposed to nest rows inside rows), we have #sidebar, a group, and #main, a block, as siblings. Current grid systems don't quite work this way, where the "row" and "column" concept intermingle.

Once we realized how similar the two concepts are, we decided to merge them into one concept, using the name block. Now we have a single layout object that can be used for content or layout.

<!-- This group becomes a block, and functions the exact same -->
<div class="block" id="container">
  <!-- As does this group -->
  <div class="vertical large-4 block" id="sidebar">
    <div class="shrink block" id="sidebarTitle"></div>
    <div class="block" id="sidebarContent"></div>
  </div>
  <div class="large-8 block" id="main"></div>
</div>

However, there was one final snag. Blocks are flex containers, which we don't usually want for actual content. So we decided to add the modifider class content, which swtiches the block from display: flex to display: block, and adds a gutter around the whole thing.

<div class="block" id="container">
  <div class="vertical large-4 block" id="sidebar">
    <!-- This two blocks are for content, not layout -->
    <div class="shrink content block" id="sidebarTitle"></div>
    <div class="content block" id="sidebarContent"></div>
  </div>
  <!-- Same with this one -->
  <div class="large-8 content block" id="main"></div>
</div>

This is how the grid syntax currently works, and we're looking to get feedback on our approach. Specifically, we're curious to know:

Martinspire commented 9 years ago

Nice to see you guys going for flexbox. Been using it myself for a while now. One problem i had quite a few times was getting minimum height for the box. The height that makes sure the content fits and not breaks any overflow or whatever. Especially when on mobile with those virtual-keyboards you will get in trouble because the content won't fit and will either overflow incorrectly or gives you tiny scrollbars with too much content to scroll.

Example to mess around with: http://jsfiddle.net/wnu18w4g/ . I'm forcing a height on that which is clearly to small but think of it as the body of your product when a keyboard is up and you are using flexbox.

gakimball commented 9 years ago

Yeah, we've run into quite a few problems with the grid on mobile which we've spent a while researching.

Another big one is scrolling panes. The grid does "fixed positioning" with a vertical flex container, and the middle area is just scrollable. Problem is, iOS loves to get finicky with this, trying to scroll the whole window instead of the inner container. The way around it is JavaScript hacks that selectively disable scrolling or prevent the propagation of the various touch events and so on. It kinda sucks that our grid will probably have a JS dependency, but y'know, mobile browsers.

If you or anyone else has experience with it, let us know!

Martinspire commented 9 years ago

Hmm, i didn't have issues with scrolling inside flexbox on iOS and others. I did it with css only and that seemed to work. Although i don't recall if i might have had the outer or inner container to display:block

I did have an issue with the iOS keyboard and rotating the device while it is shown, but that seems fixed on iOS 8. But that wasn't related to flexbox but to fixed elements.

Perhaps we should separate devices which require Javascript for legacy-support by an external dependency. I don't think iOS8, Android 4.4 (or 5 even) and WP8.1 require a lot of Javascript fallback. Older devices do but using Flexbox is already separating a few and i even feel that devices that require display:box or -webkit-display:box instead of display:flex should already be separated. Or keep the 5.x branch for older devices and go for true next-gen support on 6.x Much like jQuery did with their 2.x branch (albeit they still support IE9 and stuff).

If you are going for Foundation for Apps, you are probably better off supporting latest iOS, Android and WP than going for older support. On iOS and WP you can be sure that most users (those that buy stuff at least) will use latest OS. On Android you are already fine with 4.4. Even if that doesn't have most devices, it will increase big time in the next couple of months as devices get updated. I'm not sure what the release would be of this, but apps developed with this will already be months apart from that anyways.

gakimball commented 9 years ago

@Martinspire We spent a while butting our heads against this scrolling issue in iOS7 on Friday, and today we opened the same demo page in iOS8 and it worked just fine. So Apple fixed it! But we still need to make sure it works in iOS7 and Android 4. (And Windows Phone 8, let's say.)

Martinspire commented 9 years ago

Why iOS 7? Doesn't seem to be needed since people will be updating in the next few weeks. And the ones who don't aren't going to be big customers anyways (stats prove that).

And WP8.0 also is going to be replaced by 8.1 for most users. Since 8.0 has IE10 and 8.1 has IE11 i would drop 8.0 support asap. Takes way too long to implement legacysupport. Especially with grids and other new HTML5 stuff

gakimball commented 9 years ago

You're right, a month from now iOS8 adoption will probably be high enough for it to not matter, although it has been slower than past releases.

calebsmithdev commented 9 years ago

I just want to say that I love the new grid system. It's quick and easy - once you transfer some of the logic from F-Sites and keep yourself from nesting rows like a mad person. In response to the columns question - I like the 12 columns and I have become very adjusted to it as quick creation. As you mentioned, changing the variable to 100 would accomplish the same thing and I think that could be an option that people could take if they want a percentage column. I know that would be helpful on some occasions, but it's much quicker math (for me) with 12 as the total.

It did take me while to figure out why I was seeing extra whitespace outside of the main container for the default content.. found out it was a "container" class so that is good to know!

Keep up the great work! I am enjoying it so far and I look forward to playing with it even more.

Bernardao commented 9 years ago

I agree with @Failcookie, allowing the option to changing the variable to 100 would let us an easier way to create 5 columns, harder with a system of 12 columns.

About the class names I would prefer to stay with .group better than .block, since .group means for me that are more elements inside as columns, while a block means more about a final class with content inside but nothing else. Also imho using .content-block or .layout-block could have more sense, inside a .group always a .x-block (content or layout). Not sure if that helps you.

 <div class="group" id="container">
   <div class="vertical large-4 layout-block" id="sidebar">
     <!-- This two blocks are for content, not layout -->
     <div class="shrink content-block" id="sidebarTitle"></div>
     <div class="content-block" id="sidebarContent"></div>
   </div>
   <!-- Same with this one -->
   <div class="large-8 layout-block" id="main"></div>
 <div>
gakimball commented 9 years ago

@Bernardao I do think that was a point in favor of group and block, they both had more distinct meanings. The main issue is they're both short, one-syllable words, and we routinely confused them in conversation, especially because they overlap in functionality. (For example, unlike Foundation 5 rows, F4A's groups can have sizing classes just like blocks.)

Some other folks have also pointed out that block and content are used by CMSes, so we might need more specific classes. Maybe grid-block and grid-content? That uses the existing terms we have, but namespaces them to make them more distinct.

gakimball commented 9 years ago

@Bernardao @Failcookie Also, it will be possible to change the column count from the default of 12, but you'll probably also want to disable the grid classes then, or you're going to have like a billion. So your semantic, percentage-based grid would work like:

$total-columns: 100;

// Full width on small, 50% on medium and up
.some-column {
  @include grid-block;

  @include breakpoint(medium) {
    @include grid-size(50);
  }
}

There is potential for us to build percentage- and ratio-based grids later and let people pick, but I doubt it will be a 1.0 feature.

Bernardao commented 9 years ago

@gakimball what about using .wall and .bricks or maybe .building .floor or .doors? Or you could use .block and .group in spanish that are very similars .grupo and .bloque?

Just some brainstorming

kenwheeler commented 9 years ago

I think 12 columns is pretty standard and encompasses most designs. That said, if you were to go the percentage route, I think increments of 5 would be ideal.

In regards to naming, I'm the worlds biggest hater of "classitis". I typically do this sort of thing using sass includes just to avoid it. However, a declarative approach is really helpful for non sass users, and for people who didn't write the code initially. They can tell how big it is gonna be, approximately, just by looking at it.

My proposal is a little crazy. Attribute selectors. I know, it sounds absolutely bananas but hear me out.

Instead of loading up the class name with structural classes, delegate that to attributes. I suppose if it HAS to be valid markup, you could prefix it with data-, but this is Foundation for Apps.

See below:

http://jsfiddle.net/ku76xzLz/

Performance? Not that bad, roughly 83% of the speed of a single class selector:

http://benfrain.com/css-performance-revisited-selectors-bloat-expensive-styles/

gakimball commented 9 years ago

@kenwheeler We considered using an attribute like data-layout to store the grid classes, but ultimately we decided we were solving a problem better solved by just using mixins. The documentation for this framework will emphasize the Sass way of building components much more than the Foundation 5 docs, which puts all of the Sass stuff at the bottom.

The two classes we settled on for the grid are grid-block and grid-content. This naming convention fits better with existing components, since the name of the component is actually in the class. The namespacing prevents any conflicts with frameworks like Drupal, which use the classes block or content.

We still need to work out a few other naming conventions. One of them is related to the default behavior of the grid. Flexbox can make all of your grid columns equal height, but then none of the boxes will wrap, which is required for a traditional responsive layout. Right now wrapping is the default, and you can add the class stretch to disable wrapping and stretch the columns out. However, in our development we've found stretching to be a more common behavior and we're adding stretch to our grid blocks all the time.

So here's the question: should the default behavior be stretching or wrapping? We'll make one the default behavior, and add a class for the other.

kenwheeler commented 9 years ago

Because it's "for Apps", my vote is for stretching as the default.

gakimball commented 9 years ago

@kenwheeler We tend to agree, and also stretch is a problematic class name because a block can have a shrink class, which auto-sizes it to its natural width or height. But those are two totally separate behaviors with similar names.

I think the main distinction is that stretching makes sense for the big structural components of your app, like the panes and so on. But once you get to a content area, maybe you have a grid of cards that you need to collapse from 3-up to 2-up to 1-up. In that case you need wrapping because everything has to stack. (Although for even-width layouts like that, we have [size]-up-[n] classes that do that for you.)

jwvanderbeck commented 9 years ago

I hope you don't mind some feedback by a relatively newbie designer. My strong suit is in programming, not web design. That said I think you will find that people like me are a strong core of the new "web app" developer crowd.

I am really excited by what Zurb is doing with this new Foundation for Apps. I am building a new website that I want to give the user the same experience that they get on native device, and web apps is where it is at. The ability to have independent blocks of content that can each individually scroll, move, etc, as need is vital.

I am not a fan of the classic 12 column layout. I know really talented people can do some amazing things with it, but i'm not one of them. To me it feels like only a small step of from the 90's where you would take a Photoshop image and slice it up into cells and plop it into a webpage with a table.

Screen resolution has exploded recently, and we have websites that use 50% of the available screen size. It looks silly. I want to build web apps that can scale and become a fun, interactive experience that fills the browser window no matter how small or how large. We've gotten so good at dealing with small screens, but it feels like large screens have fallen behind. Look at the new iMac 5k display. People are going to be viewing websites on that thing that look like a sliver in the middle of the screen.

This new flex based layout system really intrigues me and I can't wait to figure it all out so that I can make amazing apps with it. I have a design that i'm prototyping right now that needs the ability to have panels of content that can move separately from everything else. Sliding in and out as needed, and scrolling as needed to deal with expanding content.

Now with all that high brow feedback out of the way, a few pieces of concrete feedback.

I think the concept of modifiers like 'content' are good. I personally think they are better than entirely new classes. Though it is obviously a conceptual thing, but I find it makes more sense to me. I have a block with or without content. .block.content, or .block - Maybe if there was a layout modifier, it would be a bit more symmetrical and clear (/block.content vs .block.layout), but that isn't a huge thing.

Anyway, there is my 2 cents. Now i'm off to keep beating on this to try and figure out how to make it do what I need :)

gakimball commented 9 years ago

@jwvanderbeck, thanks so much for your feedback!

To your point about "groups" as a concept, you're totally right, and that's why we scrapped them in favor of having just blocks. The two layout objects shared a lot of similar features, which is why we ended up merging them. The reason we're shying away from content as a standalone class is because it's a very generic term, and some CMSes (such as Drupal) use block and content classes already. Of course, class collision will always be a potential issue when you mix libraries, the word "block" is so generic that we're probably better off prefixing it with the word "grid", just to be safe.

As for scrolling, what browser are you using? We're having some troubles with Safari right now, but the newest versions of Chrome and Firefox should handle scrolling content just fine. All grid blocks will scroll by default if their content overflows.

jwvanderbeck commented 9 years ago

The scrolling is just something i'm doing wrong on my markup i'm sure. The demos scroll properly. I just need to sit down and see what markup i'm missing.

jwvanderbeck commented 9 years ago

How does this system work for vertical spacing control? I'm currently finding it hard to control what would have been row heights between my blocks.

gakimball commented 9 years ago

@jwvanderbeck Unfortunately vertical sizing is not as full-featured as horizontal sizing, which is a quirk of flexbox. You can size vertical grid units these ways:

I'm sure what you're trying to do is size with percents, and unfortunately you can't. We were hoping to make the behavior of the horizontal and vertical grid identical, but that's the one place where they aren't.

jwvanderbeck commented 9 years ago

The manual sizing method should work fine for my current needs. I'll look into that. Thanks.

jwvanderbeck commented 9 years ago

Actually let me follow up on this. In looking at my markup, i'm finding I am having trouble understanding where a block is defining a horizontally oriented block and when it is defining a vertical oriented block. I guess i'm still having issues translating from rows & columns.

.frame.vertical
    .block.shrink
        .block.content
    .block.stretch
        .block.content

So that is defining two blocks of content, stacked vertically on each other, filling the width of the browser window. I'm not sure entirely why that is, but I know it is because that is what i'm seeing.

Now I expand that:

.frame.vertical
    .block.shrink
        .block.content
    .block.stretch
        .block.small-3
            .block.content
        .block.small-3
            .block.content
        .block.small-3
            .block.content

And suddenly I have 3 columns in the second of the rows. But I don't understand why, and I don't understand the distinction that is specifying how a block is working. So yeah i'm still having a lot of confusion with the generic block terminology here.

But if I go with the flow of that doing what it does, then to me the following markup should give me a stack of 2 blocks in the 3rd column, 2nd row. But it doesn't appear to.

.frame.vertical
    .block.shrink
        .block.content
    .block.stretch
        .block.small-3
            .block.content
        .block.small-3
            .block.content
        .block.small-3
            .block.shrink
                .block.content
            .block.stretch
                .block.content

edit - Ok it looks like my problem was missing some content blocks. That works now but I still am finding it difficult to grasp what is happening.

gakimball commented 9 years ago

@jwvanderbeck So one thing to understand is that you don't need to alternate blocks and content blocks. It's not like rows and columns in Foundation, where they have to alternate. So your last example can be condensed down like this:

.frame.vertical
    .block.content.shrink
    .block.stretch
        .block.content.small-3
        .block.content.small-3
        .block.content.small-3

Blocks always move horizontally by default, and that behavior doesn't cascade down to nested grid elements. So you always need to define a vertical grid on every block that you want to have vertical children. In the above example, only the highest-level grid element (the app frame) is vertical. Those small-3 blocks will be arranged horizontally.

The grid is still missing formal documentation (and will soon be refactored slightly), so props to you for trying to figure it out :)

jwvanderbeck commented 9 years ago

@gakimball thanks for that. I'm starting to see it, but i'm still failing at getting what i'm after. What I am trying to do is Panel on the left that is always a panel. Center content. Then on the right, two vertically stacked Panels that become blocks on large screens.

No matter what I do though I can't get those two panels on the right to sit on top of each other vertically. This is the mockup i'm trying to reproduce: ssb-new-holo-mockup

I can't for the life of me find a way to do the two panels on the right. Here is my current test markup

.frame.vertical
    .block.content.shrink
        h1 This is a Header
    .block.stretch
        .panel.panel-left#panel
            p This is a panel
        .block.content
            p This is some content
        .block
            .panel.panel-right.large-block
                p This is some more content
                button(data-panel-toggle="panel") Toggle Panel
            .panel.panel-right.large-block
                p Panel content

No matter what I try though, the two right panels always end up next to each other horizontally rather than stacked vertically.

ilanbiala commented 9 years ago

Unrelated, but that thing looks cool. What's it for?

jwvanderbeck commented 9 years ago

@ilanbiala It is a planned rebuild of this site which is based on this upcoming video game

@gakimball Any thoughts on getting vertically stacked panels like above?

EDIT Ok yay! I got it working. I was apparently only missing one tiny piece. In my markup above, I just needed to make the block that my two panels were in, into a content block and boom it all works now. And it is a thing of beauty.

jwvanderbeck commented 9 years ago

Actually it looks like making that parent block a content block doesn't quite fix my issue. It does allow the two panels to stack vertically like I want, but it also is constricting the panels to the space of that block, which means I really lose the benefit of them being panels because I can't slide them open properly. They get cut off by the size of the parent.

So i'm still looking for a way to have two vertically stacked panels that operate like standard panels, open and close on top of the content underneath.

My Markup My CSS

Pushplaybang commented 9 years ago

Hi There,

This project looks amazing, thought I'd throw in my 2c about grids. Honestly when ever I've used bootstrap or given foundation a go one of the first things I sidestep is the grid in favour of something a lot more flexible.

I've been working with the (Susy SCSS grid system)[http://susy.oddbird.net/] a lot over the last year and the flexibility it gives you is incredible. Using this or something similar would allow you to setup a default to ship with foundation for apps, but not lock anyone down, allowing them to open it up on the fly. I'm not sure that you'd ever consider using a third party library like this, but conceptually I think it makes a whole lot of sense for foundation-apps.

Kind Regards

Paul

HansUXdev commented 9 years ago

Love the new flexbox grid. But I was wondering have you considered swapping out autoprefixer for "pleeease" as a post processor? I've been testing it out and it seems to have better support for vendor prefixes and it also could eliminate the need for rem calc and some of the other mixins. I've only noticed a few minor issues when you compile the scss.

maxcook commented 9 years ago

Hi guys,

for obvious reasons i would be useful to have a dropdown (actionsheet) in a menu bar, e.g. for user short links. However, the actionsheet is bound by the menu bar boundaries and makes it scrollable instead of hovering it.

zurbrandon commented 9 years ago

Thanks for the grid feedback! Lots of awesome stuff and we had a ton of debate on most of these topics. Thanks all!!!!!

djgadd commented 9 years ago

Realise I'm late to give feedback but I figure it would be better here than opening a new issue.

Would quite like to see a {size}-shrink-only set of classes (and ideally that kind of convention echoed across most of the utility classes). I find myself writing a lot of boiler code for that at the moment because my layouts go from vertical to horizontal when moving between small/medium, and shrink is overriding the classic columns syntax.

gakimball commented 9 years ago

@djgadd We do need responsive versions of the shrink class, and also probably an expand class to revert a grid element back to the default behavior, with responsive versions of that class as well.