Skip to content
This repository has been archived by the owner on Sep 5, 2024. It is now read-only.

The styles for hide/show[-xx[-yy]] are wrong #772

Closed
gkalpak opened this issue Nov 26, 2014 · 24 comments
Closed

The styles for hide/show[-xx[-yy]] are wrong #772

gkalpak opened this issue Nov 26, 2014 · 24 comments
Milestone

Comments

@gkalpak
Copy link
Member

gkalpak commented Nov 26, 2014

I think that the current implementation of hide[-xx[-yy]]/show[-xx[-yy]] is kind of broken and confusing (not sure if it is so by design or as a result of a bug in style declarations).

Based on the current styles it seems that show-xx-yy can negate hide-xx-yy, which seems to have little point (why would I want to define show-xx-yy and hide-xx-yy on the same element). Furthermore it comes to contradiction with the docs, which state that show[-xx[-yy]] "negates hide" (not hide[-xx[-yy]]).

It is makes much more sense (imo) anyway:
Either show the element "by default" and use appropriate hide-xx[-yy] attributes to hide it on specific devices or hide the element "by default" (using hide) and use appropriate show-xx[-yy] attributes to negate hide and make the element visible on specific devices.
Mixing both approaches won't help.

That said, I believe that:

  1. show is unnecessary (since elements are shown (i.e. not hidden)) without needing any attribute (and overriding hide across all devices doesn't make sense).
  2. show[-xx[-yy]] should only negate hide (on appropriate screen-sizes).

According to the above, here are the selectors that should have a display: none; style per screen-size:

any: 0 < size

sm: 0 < size < 600

  • [hide-sm]

gt-sm: 600 < size

  • [hide-gt-sm]

md: 600 < size < 960

  • [hide-md]

gt-md: 960 < size

  • [hide-gt-md]

lg: 960 < size < 1200

  • [hide-lg]

gt-lg: 1200 < size

  • [hide-gt-lg]

BTW, this is related to the problem described in #764.


I hope all this makes sense, because I used make sense too many times...

@mzbyszynski
Copy link
Contributor

Great analysis @gkalpak! I agree with most everything you wrote but I wanted to add my two cents in defense of an all powerful show attribute. For me it would be useful to have the show attribute always force an element to be visible regardless of screen size. As you point out, it would be redundant if you were creating a static template, since

<div show hide-gt-md>

would behave the same way as just:

<div hide-gt-md>

But I do think it would be useful to have show override all hide[-xx[-yy]] so that you can add it dynamically to force some content to be visible. For example, I am working on an application that displays a large amount of data elements on screen, and on smaller screens, certain data elements are not displayed by default. However, the user does have the option of choosing which data elements are visible, so if the user decides they want to see a data element that is normally hidden at their screen size, it would be nice to be able to just slap the show attribute on that element and have it appear.

Thinking about it some more as I write this, I suppose that I could achieve the same functionality by only using hide and show-gt-xx, and just removing the hide attribute to force something to appear in all screens, but I can still see a use for show in the inverse case, where you have some elements that are visible on smaller screens only that you may want to force to appear on all devices under certain circumstances.

What do you think?

@gkalpak
Copy link
Member Author

gkalpak commented Nov 27, 2014

@mzbyszynski: You definitely have some point :)
My comment about show not being any useful as a negation of hide still holds.
But I can see some usefulness in show as a negation to every hide[-xx[-yy]] attribute (for the scenarios you described).

As you too mention, this wouldn't provide any new functionality (everything would be achievable without the use of show), but it could help simplify the templates in certain cases.
The question is if this is worth the extra complexity (of documenting/explaining/memorizing that although show-xx[-yy] negate hide, show is a special case and negates them all).
(And although I don't have the answer right now, it should definitely be considered 😄)

@ThomasBurleson ThomasBurleson added this to the 0.7.0-rc1 milestone Dec 2, 2014
@ajoslin
Copy link
Contributor

ajoslin commented Dec 4, 2014

Hmm, so since this issue was created this was modified a bit.

show-{size} is currently allowed to override hide-{size}.

For example: <div hide-gt-sm show-gt-lg> will hide on 600px < size < 1200px.

However, I don't know if I like this .. it is quite confusing.

I think I actually like getting rid of the show attributes altogether ... Except maybe the one show attribute as @mzbyszynski suggested.

@ajoslin
Copy link
Contributor

ajoslin commented Dec 4, 2014

That means we end up with the following:

[hide]:not([show]) { 
  display: none;
}
@media (max-width: $layout-breakpoint-sm) {
  [hide-sm]:not([show]) {
    display: none;
  }
}
@media (min-width: $layout-breakpoint-sm) {
  [hide-gt-sm]:not([show]) {
    display: none;
  }
}
@media (min-width: $layout-breakpoint-sm) and (max-width: $layout-breakpoint-md) {
  [hide-md]:not([show]) {
    display: none;
  }
}
@media (min-width: $layout-breakpoint-md) {
  [hide-gt-md]:not([show]) {
    display: none;
  }
}
@media (min-width: $layout-breakpoint-md) and (max-width: $layout-breakpoint-lg) {
  [hide-lg]:not([show]) {
    display: none;
  }
}
@media (min-width: $layout-breakpoint-lg) {
  [hide-gt-lg]:not([show]) {
    display: none;
  }
}

Thoughts?

@mzbyszynski
Copy link
Contributor

Makes sense to me. I can't think of a use-case for the show-xx attributes that couldn't be accomplished using the hide-xx.

@gkalpak
Copy link
Member Author

gkalpak commented Dec 5, 2014

@ajoslin:

Hmm, so since this issue was created this was modified a bit.
show-{size} is currently allowed to override hide-{size}.

It was suppose to work like this when I created the issue, but it didn't work as expected.

For example: <div hide-gt-sm show-gt-lg> will hide on 600px < size < 1200px.
However, I don't know if I like this .. it is quite confusing.

Indeed having show-{size} overwrite hide-{size} makes little sense and is only useful for cases where you want to show something on small and large screens only (which is a weird and unlikely use-case). In any case, for those rare use-cases you can accomplish the same thing

I think I actually like getting rid of the show attributes altogether ... Except maybe the one show attribute as @mzbyszynski suggested.

I am pretty sure @mzbyszynski didn't suggest keeping only the show attribute. He suggested keeping the show attribute (along with show-{size}) instead of getting rid of it (as I originally suggested).

Regarding #772 (comment):
I don't like this. "The symmetry" is important for making it easy/concise to both hide and show at specific screen sizes. Your suggestion makes it difficult/verbose to hide on medium or large screens. E.g.:

// Show on medium only
hide show-md  -->  hide-sm hide-gt-md

// Show on large only
hide show-lg  -->  hide-sm hide-md hide-gt-lg

(Not only is it more verbose, but it is much less readable as well, i.e. you have to think more to find out what it does.)


Considering the above, I think the selectors that should have display: none; per screen-size (taking into account @mzbyszynski's suggestion) are the following:

sm: 0 < size < 600

gt-sm: 600 < size

md: 600 < size < 960

gt-md: 960 < size

lg: 960 < size < 1200

gt-lg: 1200 < size

I write them like this (instead of proper SCSS), because I find it more readable. If we decide to go with this approach, I can write the actual rules.

@mzbyszynski
Copy link
Contributor

HI @gkalpak & @ajoslin,

My original suggestion (the way I was thinking about it anyway; I may not have communicated it properly) was for keeping the show attribute around and making it trump the all the hide* attributes for cases where you need a way to dynamically force an element to display without having to worry about screen size or what other attributes the element already had. I didn't have any real opinion about the show-xx attributes.

I guess it is a trade-off: symmetry and more concise html versus simplicity and clarity of the API. Personally I think I agree more with @ajoslin. I would prioritize a simpler API over concise html. I don't mind opinionated frameworks, and I think in most cases providing one way to accomplish a given use case is better than providing multiple ways. It is generally easier to develop, test, maintain and document the former, and having only one way to do something should prevent (or at least cut down on) semantic arguments about which way is the right way to code something. But I suppose it boils down to what the design goals/priorities are for this project and the core team. I haven't found too much about what these are beyond this statement from the README:

Our goal is to deliver a lean, lightweight set of AngularJS-native UI elements that implement the material design specification for use in Angular single-page applications (SPAs).

Is having all these flavors of hide-xx and show-xx still lightweight and lean? And if the answer is yes (and I'm just being the devil's advocate here) then why not add show-lt-xx and hide-lt-xx attributes as well?

I could probably be convinced either way 😄, but I keep thinking of a moment when I first started using ngMaterial: I had a little trouble getting my head around the layout options, but reading @pandaiolo's comments on #494 clarified it for me... if it is a "mobile first" framework then I need to make my default design the mobile screen and add exceptions, duh! Of course, the layout system now is a lot more complex/flexible than it was when those comments were written so they may no longer apply, but putting that aside--once I understood the concept I was able to follow this approach and move on with my project instead of fighting with the framework to make it fit the way I was thinking about my application. I mention this as an example of how simplicity & having fewer options for accomplishing a task can sometimes be more help to a developer than the alternative.

That's where I'm landing on this issue today anyway. Great discussion so far, and I'm looking forward to further debate!

-Marc

@ajoslin
Copy link
Contributor

ajoslin commented Dec 5, 2014

@gkalpak I still like the lack of show better - for the reasons that @mzbyszynski said - it is simpler, and leads to one way to do things.

Your example is rather compelling when I look at it:

// Show on medium only
hide show-md  -->  hide-sm hide-gt-md
// Show on large only
hide show-lg  -->  hide-sm hide-md hide-gt-lg

But then there's this very confusing counterexample that we allow the developer to do:

hide-gt-sm show-gt-lg //What should this do? Either way, it's confusing.

For this reason, I like removing the show attributes.

@ajoslin
Copy link
Contributor

ajoslin commented Dec 5, 2014

@ThomasBurleson since this discussion is already in progress, we'll keep it here.

@gkalpak
Copy link
Member Author

gkalpak commented Dec 5, 2014

@ajoslin: I defintely don't think it is a good isea to remove the show-{size} attributes, but it is what it is.
I do believe this will make people unhappy and there will be several issues submitted. So, if you end up implementing them anyway, I will stop by and say "I told you" 😛

That said, I appreciate you sharing the reasoning and thoughts behind the decisions and I totally understand you can't keep everyone satisfied.
Really like this project and the work everyone is putting into it is really great ✨

@ajoslin
Copy link
Contributor

ajoslin commented Dec 8, 2014

With your opinion @gkalpak and discussion with @rschmukler, we've decided to keep it as is. It's the best option we have right now.

Thanks for the input all!

@ajoslin ajoslin closed this as completed Dec 8, 2014
@gkalpak
Copy link
Member Author

gkalpak commented Dec 8, 2014

@ajoslin, @rschmukler: I don't really understand what "It's the best option we have right now" is supposed to mean. Both @ajoslin's suggestion and mine are much better than the current one (although I prefer mine for obvious reasons). The problem with the current implementation (and the reason I opened this ticket in the first place) is that right now it is broken :)

A few reasons:

  1. The docs describe something different than what you seem to want to implement. (Although the docs describe what I believe should be implemented.)
  2. It does not make sense to have show-xx-yy cancle out hide-xx-yy. There is absolutely no reason to use both attributes on the same element.
  3. If I have [hide] on an element, it will be hidden no matter what (unless I have [show] on the same element). This practically renders hide useless.
  4. If you have [hide-sm-lg][show-lg] on an element, it will be shown always.

(I haven't exhaustively looked for cases that don't work, but I am very confident there will be more.)

I understand that the team may decide on a different approach (than what I suggested), but I believe it should be implemented correctly/bug-free.

I propose you (I mean the team) write down what is the expected behaviour, so we can 1. update the docs and 2. submit issues on specific CSS bugs.

I hope I don't sound like that cranky guy; I am just trying to help :)

@ajoslin ajoslin reopened this Dec 8, 2014
@ajoslin
Copy link
Contributor

ajoslin commented Dec 8, 2014

I didn't realize you had suggested the "show-gt-* only overrides hide" solution.

I don't like this because it is not intuitive ... When I see show-gt-lg, I would think it would override hide-gt-md.

@gkalpak
Copy link
Member Author

gkalpak commented Dec 8, 2014

  1. Even if you decide that you don't like what I proposed (which is a different matter), the current implementation is not working as expected (see my comment above).
  2. I really don't find intuitive that hide-gt-md gets cancelled by show-gt-md. Why would I put both attributes on an element ? Maybe I am missing something. Can you name a use-case when this makes sense (putting both attributes on the same element) ?

Basically, you can think of it as ngShow vs ngHide. The purpose of each is not to cancel each other out, but to provide the same functionality from different perspectives. You don't actually need both, but one might read more natural than the other in certain cases.

It is the same story with show-{size} overwriting hide vs hide-{size} overwriting show (only in the latter case, you don't need show, because elements are visible by default).

You could achieve the same functionality with either one (thus your proposal of removing show-{size} does work), but having both available enables writing HTML that reads easier and is less verbose (thus my suggesting keeping them both).

@altufaltu
Copy link

I'm thoroughly confused with these attributes.
How do I show a section on screens greater than medium?
There isn't hide-lt-lg and show-gt-md or hide-gt-md show-gt-md or hide-gt-md show or hide show-gt-md doesn't seem to work.

My sugession is to have hide-xx, hide-gt-xx and hide-lt-xx for all sizes, with a single show attribute that overrides any hide-* attribute.

@ajoslin
Copy link
Contributor

ajoslin commented Jan 14, 2015

@altufaltu try hide show-gt-md or hide-sm hide-md.

@ajoslin
Copy link
Contributor

ajoslin commented Jan 14, 2015

@gkalpak so I'm finally getting to this.

The changes you suggested still broke in some cases.

After much thought and testing, I've started over with a simpler approach. I couldn't find any problems with it.

Please poke at it and let me know your thoughts!

/**
 * `hide-gt-sm show-gt-lg` should hide from 0px to 1200px
 * `show-md hide-gt-sm` should show from 0px to 600px and >960px
 * `hide-gt-md show-gt-sm` should show everywhere (show overrides hide)`
 */

// SMALL SCREEN
@media (max-width: $layout-breakpoint-sm) {
  [hide-sm], [hide] {
    &:not([show-sm]):not([show]) {
      display: none;
    }
  }
}

// MEDIUM SCREEN
@media (min-width: $layout-breakpoint-sm) and (max-width: $layout-breakpoint-md) {
  [hide], [hide-gt-sm] {
    &:not([show-gt-sm]):not([show-md]):not([show]) {
      display: none;
    }
  }
  [hide-md]:not([show-md]):not([show]) {
    display: none;
  }
}

// LARGE SCREEN
@media (min-width: $layout-breakpoint-md) and (max-width: $layout-breakpoint-lg) {
  [hide], [hide-gt-sm], [hide-gt-md] {
    &:not([show-gt-sm]):not([show-gt-md]):not([show-lg]):not([show]) {
      display: none;
    }
  }
  [hide-lg]:not([show-lg]):not([show]) {
    display: none;
  }
}

// BIGGER THAN LARGE SCREEN
@media (min-width: $layout-breakpoint-lg) {
  [hide-gt-sm], [hide-gt-md], [hide-gt-lg], [hide] {
    &:not([show-gt-sm]):not([show-gt-md]):not([show-gt-lg]):not([show]) {
      display: none;
    }
  }
}

@gkalpak
Copy link
Member Author

gkalpak commented Jan 14, 2015

I am very happy to this being dealt with (finally 😛). Thx @ajoslin
I will take a look and let you know if I see anything "weird".

Would still be interested to know in what cases my suggestion broke :)

@gkalpak
Copy link
Member Author

gkalpak commented Jan 14, 2015

@ajoslin: Haven't tested it, but "theoretically" it looks fantastic (it's indeed more complete than my "basic" suggestion). I have only left a couple on comments on incorrect comments (which might confuse future maintainers or "sourcerers").

I like the fact that it sets up a proper "priority" of each rule "family" (it might be worth documenting more explicitly). From "strongest" (beats all) to "weakest" (looser):

  1. show
  2. show-xy
  3. hide-xy
  4. show-gt-xy
  5. hide-gt-xy
  6. hide

@mzbyszynski
Copy link
Contributor

Looks great @ajoslin! 👍

@thomasphan
Copy link

The styling fails at the breakpoint of 600px. In the API reference demo for hide and show attributes, https://material.angularjs.org/#/layout/options, both of the md-subheaders are hidden on 600px devices.

@gkalpak
Copy link
Member Author

gkalpak commented Feb 17, 2015

It works fine for me (Chrome 40 on Windows 8.1). What browser/platform are you trying this on ?

@thomasphan
Copy link

I am testing with Chrome 40 on OS X Yosemite and Chrome 40 on Windows 7 with the same result.

Sorry for not being clear. Because hide-sm displays none at max-width: 600px and hide-gt-sm displays none at min-width: 600px to max-width: 960px, there is not a way to show one and not the other at 600px. Both hide-sm and hide-gt-sm will display none at 600px.

Thanks @gkalpak

@gkalpak
Copy link
Member Author

gkalpak commented Feb 17, 2015

@thomasphan, I see what you mean. Indeed there is an issue at exactly 600px (and probably other breakpoints as well).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants