thoughtbot / neat

A fluid and flexible grid Sass framework
https://neat.bourbon.io/
MIT License
4.42k stars 424 forks source link

Allow $direction on span-columns #79

Closed paulozoom closed 10 years ago

paulozoom commented 11 years ago

Currently, it’s impossible to have a single floated right element in a series of floated left elements (or vice-versa).

This may not seem important at first, but it’s a issue that easily arises when working in responsive designs.

An example from a project I’m working on. It’s a <footer> of a magazine <article>. It includes sponsor information, author bio, and illustrator bio.

On a narrow viewport, I want to present the content as such:

+---------------+
|               |
|   .sponsor    |
|               |
+---------------+
|               |
|   .author     |
|               |
+---------------+
|               |
| .illustrator  |
|               |
+---------------+

So, naturally, I have to write the following HTML:

<footer>

  <div class="sponsor">
  </div>

  <div class="author">
  </div>

  <div class="illustrator">
  </div>

</footer>

However, on a wider viewport, I want each <div> to take 4 units of a 12-unit flex grid, and have the sponsor at the far right, as such:

+---------------+---------------+---------------+
|               |               |               |
|   .author     | .illustrator  |   .sponsor    |
|               |               |               |
+---------------+---------------+---------------+

However, that’s not so easy right now. I could use span-columns but would have to manually override float and margin-right, as well as set margin-left myself.

So, what I propose is a $direction argument on span-columns, that I could use on .sponsor for this effect. Perhaps seeing as row now has direction support, $reverse is a better name, so this argument would in fact reverse the direction of the current row for the specific element it’s used on.

There wouldn’t be a problem with the &:last-child selector preventing a margin, because the reversed element would have margin to compensate for that, and the new default clearing behavior of omega isn’t an issue if changed to clear: both.

This is an issue that occurs often in responsive designs, as the order of HTML elements needs to match the visual presentation of content in a single-column design, so I believe it’s important enough to be brought up for consideration.

kaishin commented 11 years ago

Thanks for bringing this up. I have been thinking of this for a while now but I'm still wary of other side effects that this might have. I will experiment with it and see how it turns out.

brnrdog commented 11 years ago

It would be great, I'm looking forward for it. I believe this is an essencial feature for RWD, it's a way to provide content choreography.

jeffbkk commented 11 years ago

We can still use bourbon flex-grid() mixin and decide how you want to float elements if you set bourbon's flex-grid variables to match what neat is doing in _grid_settings like so:

$column: 90px; // or em or whatever $gutter: 24px // same

$fg-column: $column; $fg-gutter: $gutter;

dalgard commented 11 years ago

+1

kaishin commented 10 years ago

I'm aiming in the next major release to make all display/direction changes block-based. With that, wrapping a single call of span-columns in a block that shifts the direction would allow you to handle this use case.

paulozoom commented 10 years ago

@kaishin Fantastic. Thanks for all your hard work on this.

kaishin commented 10 years ago

As of #200, the direction(){...} mixin will handle everything related to direction. Closing this for now to keep span-columns straightforward and self-contained.

archebyte commented 7 years ago

Sorry to bump this but I've been searching all day for the solution to this. in 1.7.x I could use direction-context(right-to-left) to switch float and margins. This was awesome and easy. I cannot for the life of me figure out how to do the same in Neat 2.0. If you could point me in the right direction (pun intended) I'd appreciate the proper way to handle this.

kgcreative commented 7 years ago

@plebeian-org in Neat 2.0, you can specify the direction as part of the grid definition:

$my-custom-grid: (
  columns: 12,
  gutter: 20px,
  media: 1200px,
  color: rgba(#00d4ff, 0.25),
  direction: ltr,
);

direction can be ltr or rtl, which will reverse the float direction of any columns inside the grid

archebyte commented 7 years ago

Hey thanks I was looking for changing only the direction in the grid-column mixin, not realizing you must create two grids, one for ltr and one for rtl (as below). Please let me know if I'm insane here, or another way to do this, and thanks for the quick response. :)

$my-custom-grid: ( columns: 12, gutter: 20px, media: 1200px, color: rgba(#00d4ff, 0.25), direction: ltr, ); $my-custom-grid-right: ( columns: 12, gutter: 20px, media: 1200px, color: rgba(#00d4ff, 0.25), direction: rtl, );

kgcreative commented 7 years ago

There's a few ways you could do it, depending on how you have your project structured.

If the only difference between the different grids is direction, then I would define your $neat-grid to have everything, and then I would define a second $rtl grid that only has the direction property on it.

Alternatively, you could do it within a $grid-media() block if you wanted to scope it.

See https://codepen.io/kgcreative/pen/oGyLJb for a couple approaches

whmii commented 7 years ago

@plebeian-org Agree that the simplest way is to set up 2 grids.

Based on your example it would look like

$my-custom-grid: (
    direction: ltr,
);
$my-custom-grid-right: (
    direction: rtl,
);

.i-go-to-the-left {
    @include grid-column(3, $my-custom-grid);
}

.i-go-to-the-right {
    @include grid-column(3, $my-custom-grid-right);
}

I'd be interested in seeing what you are trying to achieve since there may be a more simple solution. A screenshot or doodle would work.

archebyte commented 7 years ago

Thanks @kgcreative for the example. Giving me some 'A-ha' moments. For instance, I was not aware that you can specify a map in grid-container, as the docs here don't say this is possible: https://neat.bourbon.io/docs/latest/#grid-container I was, however, trying to do exactly this in other ways unsuccessfully.

So this ( @include grid-container($rtl); ) seems to imply that it uses only the direction rule in the $rtl map, and also sets the context for all grid-column within that (rtl) container? Mind blown, but I have to say not very obvious given the docs as mentioned don't show this.

In your example, this works @include grid-column(1 of 4, $rtl); since $rtl only contains direction and screen:, and because $nead-grid is used for all grids at this point. I'm using many grids at different media points, so I opted for just being explicit, as @whmii has suggested.

Ok, so now my assumption is that as long as I've set up a context (eg. a grid map $tablet) for a container (grid-container($tablet), I can then use the minimal $tablet-rtl to switch direction using grid-column(4, $tablet-rtl), since we are now assuming I'm already in my $tablet context, and my $tablet-rtl only needs to contain my needed direction change: $tablet-rtl : { direction: rtl } ...as long as $tablet map prior has all the other grid settings: $tablet: ( columns: 8, gutter: 20px, media: 725px, color: rgba(127,50,50,0.3), direction: ltr ); If I'm correct here, this is badass, and y'all are geniuses! :) But let me know if I'm going down the wrong road. The example was super helpful. I can't wait to test this out. Thanks!

archebyte commented 7 years ago

Just a note to say in the docs, clicking on View Source shows that you can pass a map. I didn't dig that far, so missed it:

@mixin grid-container($grid: $neat-grid) {....

kgcreative commented 7 years ago

@plebeian-org - just a note - grid-container can consume a grid, but i don't believe it sets the context for all it's children. Currently the only way to really do that is to use @include grid-media($media-query) - any objects instanced inside that media query inherit the context.

archebyte commented 7 years ago

Ah Ok. Thanks, this will get some testing! Thanks again for the detailed examples!

kgcreative commented 7 years ago

(But yes, you're headed in the correct direction. And if you're inside a media query tablet context, you should be able to instance a grid-container(1 of 3, $rtl) object scoped to just rtl / ltr and it should work!.)

archebyte commented 7 years ago

Super Bueno, thanks!