Toasts should ideally be visible no matter where I am on the screen if I give no container element and set the position to one of the corners. Thoughts on setting it to position: fixed;
in this case?
@ilanbiala I think it might be how it is now so that it can bump the md-fab
buttons up a bit when it opens.
Also it moves correctly when I scroll are you sure you're using md-content
correctly? If so could you please make a plunker so we can confirm this.
I'm looking into a good solution for this. The reason that a simple position fixed doesn't work is because, what if there's a fab button? What if there's a toolbar?
I'll be looking into a good solution for 0.7.1
To me it seems the toast scrolling around is much more broken than it eclipsing a FAB or toolbar for a few seconds. Toast is used for short-term important things we definitely want the user to see.
I'd rather wait for a better fix. If a toast goes over a fab it will be hard to read anyways so it hardly seems better than the current situation.
I'd say just apply the position:fixed
locally if you prefer that.
Pseudo code implementation for toast onShow... for future reference
onShow() {
var fabs = document.querySelectorAll('md-fab');
var intersectingFabs = fabs.filter(willIntersect);
options.intersectingFabs = intersectingFabs;
angular.forEach(intersectingFabs, function(el) {
el.classList.add('md-toast-intersecting') // transition animation
if (position.indexOf('top') != -1) el.classList.add('md-toast-enter-from-top'); // set position accordingly
})
var toolbars = document.querySelectorAll('md-toolbar');
var intersectingToolbars = toolbars.filter(willIntersect);
if (intersectingToolbars.length) {
element.addClass('md-with-toolbar') // change position relatively
element.style.top = calculateOffsetToNotIntersect(element, intersectingToolbars[0]);
}
}
Agree, toasts should be always visible.
+1
+1
+1
I'm on the 'always show' team. Suppose you have two fab buttons, user is about to click the bottom one, then a toast pushes them both down and the click the wrong one.. Buttons shouldn't move around unexpectedly.
I just edited my angular-material.js
file: line 11979 'md-' -> 'md-fixed-'
then in my css
md-toast {
z-index: 10000;
}
.md-fixed-top {
position: fixed;
top: 66px; // size of my navbar + 16px
}
.md-fixed-right {
position: fixed;
right: 16px;
}
... etc for left/bottom
@ThomasBurleson @rschmukler @robertmesserle can we get some discussion going to resolve this? As of now, If I am in the center of a scrollable page, no matter where I put the toast I won't see it, which defeats the purpose of the toast. Is there a better option than position fixed?
The Team's concern is still this:
@ThomasBurleson
Things that pop up seemingly randomly to the user shouldn't move clickable buttons -> have the toast overlap FABs you don't want to cause http://i.imgur.com/C0biWU3.gif
For toolbars, pick a default, users can override it in their css if they need to
@charliewynn - Please read the Material Specifications for Toast
@ThomasBurleson If we're strictly following the spec then
"Toasts are similar to snackbars but do not contain actions" and it implies that toasts should only animate from the bottom
I know my suggestion isn't perfect.. but it is so much better than showing toasts off-screen
Just chiming in, for my application I have an md-toolbar on top of which the toast appears. I am ok with that as long as it sits on top of anything that is there, instead of moving that elements position.
Also, as my page is scrollable, any info I wish to show to the user via the toast becomes useless as the toast is not visible when the user has scrolled to the middle of the page.
Setting the toast to appear at the bottom also causes issue reported in #2936
Fixing the position seems currently the better option unless someone can suggest something better. Cheers!
@ThomasBurleson how was this resolved? Are toasts position: fixed
now?
Toasts are position:absolute;
If scrolling presents an issue, then perhaps we should auto-hide toasts on scroll events.
@ThomasBurleson Is that the final resolution for this issue? If you hide a toast on scroll events, then what happens if I show a toast while a user is scrolling...He won't see it, but I don't know that.
@ilanbiala - let's reopen this for now. But it definitely is a lower priority issue... as we are focused on triage and delivery of v1.0.
Ok. Just to get some more information and maybe to allow one of us to propose a solution, what are you guys currently thinking about other than covering toolbars and FABs? What are the alternatives as of now?
@ilanbiala -
@ilanbiala Could you make a demo for this? My stay where there supposed to when I scroll and they nudge fabs properly.
Also I just found #3848 which might explain the fabs not being nudged when they should.
@epelc using any custom CSS? I have to add in position: fixed
to get it to stay.
@ilanbiala the only custom css I have is adding position: fixed;
to my fabs. But it's required because I define all my fabs inside of md-content
. But my toasts are scrolling correctly even without the fabs.
why not do something like this: http://codepen.io/anon/pen/MwqxVg ??
@ThomasBurleson what do you think of @TitForTat's demo?
+1
+1
+1. is it "fixed" yet?
+1
+1
+1
Maybe best option is to have an option on $mdToast to position them fixed. Being able to select the parent is helpful but I want to use a toast on a large gallery and unfortunately position fixed is the easiest way to have it show up at the bottom of the screen that way irregardless of scrolling. I tried using md-content to control the height of the box but using layout-wrap means the md-content ends up with the height of all the rows at once. md-virtual-repeat is not an option either at this stage as it does not support wrapped rows of content it seems according to some other issues.
Love the package by the way. I hope my thoughts and use-case are helpful for determining a path. Let me know if a pull request is welcome.
This is a non-issue i wonder why we are still debating. It should clearly be fixed, what gives?
+1
+1
+1
+1
Either have the toast block elements, or push those elements away. Nowhere in the Material Design specs does it say toasts should appear where-ever they can because a page got scrolled. The way it is now is terribly designed.
+1
+1 -- Frustrating
A fix for this would be great. +1
Quote from similar issue
This can be probably fixed with the same approach of #8184.
A fixed position, won't work, because we need the toast to be in in relative to the parent.
Fixed toasts will be always in relative to the window.
Dunno. Don't wanna be an asshat. It's just the solution I'm using. It's breaking from the whole "material" view but hey, it works with scroll. There's an angular port for it: https://github.com/Foxandxss/angular-toastr
I suggest that the position
property of mdToast
configuration can be supplied with 'fixed'
to create a 'fixed'
toast
Example: $mdToast.simple().position('fixed top right').textContent('I want to be fixed')
Sometimes, there is no FAB and I just want the toast to be fixed.
+1
+1
+1
Had to use this approach by @dani3l, found here:
https://github.com/angular/material/issues/3539
1) Apply layout="column"
to body (this must exist at least at ng-controller level)
2) Wrap my content with <md-content>...</md-content>
3) Prevented double-scroll-bars flickering issue during the toast animation with:
body.md-toast-animating {
overflow: auto !important;
}
// Using v.1.1.0-xxx? Change to body._md-toast-animating
+1 .. I was expecting it to work like CodeSeven's Toastr.
Also if the screen is small in the Demo(900px or less), the toast shows at the bottom, but the FAB moves down, even though nothing is pushing it down.
If the screen is enlarged while the toast is open at the bottom, it doesn't move to the top.
I don't understand why "top right" toast moves to the bottom if the screen is too small. At least it should stay at the top and 100%, but why bottom?
(See Edit at the bottom for another solution that "makes sense")
This issue is directly related to the element that the toast is opening against.
When developing an angular-material app, it can be confusing which element is taking the full scope/vertical length of the page vs which elements might be affected by the oft-included height: 100%
styles.
For example, having html
and body
as height:100%;
while having several children elements at work, can cause some layout issues if you attach items with abolute
position to the body itself, because the body is only 100%
height, starting from the top of the viewport. Meaning that when you scroll, the body is no longer there, it's just overflow.
Sure, that's confusing, but the solution is to identify WHICH ELEMENT your ACTUAL CONTENT is under. And using the parent
option of the $mdToast
directive.
For example, there's a serious problem when using $mdToast
within an $mdDialog
, and this fixed the issue:
$scope.toast = $mdToast.show({
parent : angular.element('.md-dialog-container'), // use a parent container! yours may differ
template : '<md-toast>\
<span flex>Successfully logged in!</span>\
</md-toast>'
});
In your case(s), try using Chrome's inspector to identify which element actually contains the content, and see if this solution helps.
Until the material team comes up with something better, this seems to be the best bet for now.
EDIT - I realize the above is very important, but doesn't address the other separate issue presented here which seems to be related to the mdToast not scrolling with the body when it seemingly should.
The _problem_ with setting position: fixed
on the <md-toast>
is quite obvious when you observe that there is a config option on the md-toast
called parent
- which quite descriptively positions the toast _relative_ to that DOM element. This is necessary in many situations, a good example being the one described above.
My _solution_ to this.
First, observe again that on mobile devices, the <md-toast>
is always displayed at the bottom. This means that at below 960px, the toast breaks whatever position: X Y
config setting you gave it, and sits at the bottom of the container. This is defined in the material design spec, so it probably won't be changed anytime soon. When this happens, the toast
will just have a single class called _md-bottom
. We can target the toast in these instances by using the following CSS, and making ti act as we need to:
In SCSS:
@media (max-width: $layout-breakpoint-sm - 1) { // $layout-breakpoint-sm is 960px by default in angular-material
md-toast {
&._md-bottom {
&:not(._md-right):not(._md-left) {
position: fixed;
}
}
}
}
or is CSS:
@media (max-width: 959px) {
md-toast._md-bottom:not(._md-right):not(._md-left) {
position: fixed; } }
An optional second fix simply applies position: fixed
when the toast's parent
is the body
element. This occurs when we set no parent
config option on the md-toast
In most cases, this means we really want that toast to scroll with the page. So use this:
body {
> md-toast { // the ">" selector selects only immediate descendants of...
position: fixed;
}
}
+∞
In case it is helpful for others, here is the simple workaround that worked for me. Other solutions listed above didn't suit my situation.
Add the following element to the end of your <body>
section:
<div id="toast-container"></div>
Then specify this container when you create your toast:
var toast = $mdToast.simple().textContent(msg)
.parent($("#toast-container"));
$mdToast.show(toast);
Finally, add the following rule to your CSS:
#toast-container
{
position: fixed;
bottom: 0;
z-index: 999;
overflow: visible !important;
}
The overflow
property is necessary to allow the animation to work.
In my solution, I made the page scrollable with md-dialog/md-toast, and md-toast to show on top of the viewport (not using a fixed position).
1) Comment these code that change the body to a fixed position in angular-material.js:
var hasVerticalScrollbar = body.scrollHeight > body.clientHeight + 1;
/*if (hasVerticalScrollbar) {
angular.element(body).css({
position: 'fixed',
width: '100%',
top: -viewportTop + 'px'
});
}
if (body.clientWidth < clientWidth) {
body.style.overflow = 'hidden';
}
// This should be applied after the manipulation to the body, because
// adding a scrollbar can potentially resize it, causing the measurement
// to change.
if (hasVerticalScrollbar) {
documentElement.style.overflowY = 'scroll';
}*/
return function restoreScroll() {
// Reset the inline style CSS to the previous.
body.style.cssText = prevBodyStyle;
documentElement.style.cssText = prevDocumentStyle;
// The body loses its scroll position while being fixed.
//body.scrollTop = viewportTop;
};
2) Add CSS to .md-dialog-container (this is provided by @zilions https://github.com/angular/material/issues/4124):
.md-dialog-container {
height: 100vh !important;
top: 0 !important;
position: fixed !important;
}
3) Make md-toast to show on top of the viewport in angular-material.js:
var isSmScreen = !$mdMedia('gt-sm');
element = $mdUtil.extractElementByName(element, 'md-toast', true);
var viewportTop = $mdUtil.getViewportTop();
element[0].style.top = viewportTop+"px";
options.element = element;
+1 @BigBadaboom workaround. Thanks!
In case it is helpful for others, here is the simple workaround that worked for me. Other solutions listed above didn't suit my situation.
Add the following element to the end of your
<body>
section:<div id="toast-container"></div>
Then specify this container when you create your toast:
var toast = $mdToast.simple().textContent(msg) .parent($("#toast-container")); $mdToast.show(toast);
Finally, add the following rule to your CSS:
#toast-container { position: fixed; bottom: 0; z-index: 999; overflow: visible !important; }
The
overflow
property is necessary to allow the animation to work.
Great workaround, thank you! I also had to override the style for smaller screens (smartphone):
md-toast {
position: fixed !important;
}
I really appreciate people helping others in this thread and posting constructive ideas and feedback!
However, while there are a lot of rough descriptions and ideas in this thread, I don't see any CodePen demos that clearly demonstrate the issue. If I missed one (I tried to read all of the comments), please just re-post the CodePen link for me.
Can anyone submit a CodePen demo that clearly demonstrates the problem so that I can consider and verify a solution?
Requested CodePen reproduction not provided.
There is a codepen in the bug #3539 which was marked a duplicate of this one.
http://codepen.io/anon/pen/zGRZav
Here's another one. The toast appears off screen. (Click the button and then scroll down quickly to see the toast).
Most helpful comment
In case it is helpful for others, here is the simple workaround that worked for me. Other solutions listed above didn't suit my situation.
Add the following element to the end of your
<body>
section:Then specify this container when you create your toast:
Finally, add the following rule to your CSS:
The
overflow
property is necessary to allow the animation to work.