What does it mean to "apply a global class name"? - css

I'm trying to build my interface using Material-UI (current version is 3.1.2.)
A while ago when I was using Bootstrap4, I added style="overflow-y: scroll; height: 100%" to my head tag to always show a scrollbar to stop the app from jumping around when the page content grew longer than the screen.
Now that I'm trying to use Material-UI, the overflow setting seems to cause problems when combined with Material-UI's popup components (popper, menu, etc.)
I read in the FAQ that this is a known issue with a workaround: https://material-ui.com/getting-started/faq/#why-do-the-fixed-positioned-elements-move-when-a-modal-is-opened-
But I'm not sure what that's telling me to do.
What is implied by the phrase "apply a global class" in the following?
"apply a global .mui-fixed class name ... to handle those elements."
Where do they intend that mui-fixed would be added - to every component in my app? To the anchor of the menu/popper? Or do they mean that I'm supposed to apply it "globally" (ie. high up in the React page component hierarchy somehwere?)
In the meantime, as a workaround, I've just removed the overflow styling from my html element.
The app content still jumps about when the content grows/shrinks across page size, but it seems less ugly than when I was using Bootstrap.
I tried adding the mui-fixed class to my body, so when the app starts, it looks like:
<body style="overflow-y: scroll; height: 100%" class="mui-fixed">
So when the page is short, there is a disabled scrollbar. If the page grows, the scrollbar becomes enabled.
Then, while the menu popup is displayed, Material-UI changes it to this:
<body style="overflow: hidden; height: 100%; padding-right: 17px;" class="mui-fixed">
Which looks fine, regardless of the content's length. But then when the menu is dismissed, Material-UI changes the body element to:
<body style="height: 100%; padding-right: 0px;" class="mui-fixed">
The overflow style is gone and this results in the scrollbar being removed entirely if the page content is shorter than the window - so the page content "jumps" across to fill the space from the missing scrollbar.

This is for scrollbar if I got it correct, then it would be apply "globally" one time.

in your styles.ts you can add:
'#global': {
'.mui-fixed': {
// something here
},
},
and it will apply globally!

Related

Scrollbar behavior on different browsers

Let's say we have 2 <div> elements, one being the parent, other being the child.
Is there a way to make only the parent <div> scrollable on Chrome and only the child <div> scrollable on FireFox?
This might sound a bit weird, but this is something I really need to implement on my project, because FireFox is acting really weird on that matter.
Thanks in advance.
UPDATE:
Here's a simplified description of the project I mentioned.
I'm intending to design a personal HTML template with page transitions. So each page will be displayed/hidden with a transition effect when user clicks on a menu item.
I'm using a very simple transition effect I wrote myself. So, <div id="main"> is the parent and some <div class="inner-page"> are the children. Needless to say that, based on their content, each .inner-page has different height.
For #main I've set overflow-y: scroll;. On Chrome it works flawless. So, with every .inner-page being displayed, the length of the scrollbar is updated based on the height of the active page.
On FireFox however, it's a different story. The length of scrollbar doesn't change and is always the same,
based on the length of the page which has the most and longest content. So when other pages (which have fewer content) are active, there's always a huge empty scrollable area at the bottom of that active page.
An alternative solution I tried (which worked) was to set overflow-y: scroll; for .inner-page instead of #main to solve the scrollbar length issue. But then I had to hide the scrollbar, because with each page transition, the scrollbar comes and goes with the page as well, something that doesn't look good at all.
Follow this CodePen link to see a simplified version of my code and how the scrollbar behaves differently on Chrome and FireFox.
Check the browser on page load, Here and add set the overflow of div hidden for Firefox.
overflow: hidden;
Lets say you added class ".firefox-scroll"
.firefox-scroll { overflow: hidden; }

Make Full Page Scrollbars Control Table with Sticky Headers (CSS Only)

The following sandbox shows code that works perfectly well for a Material UI Table placed within a Paper component with a sticky header: https://codesandbox.io/s/2n40y
I would like the scrollbars (horizontal and vertical) to appear at the edges of the browser page, bottom and right respectively, yet still control the scrolling of the Table itself.
Currently I am only able to do this when removing the table from the Paper and making it a child of the page directly -- or a child of a main div that would span the full page height. Yet I need the Paper component to remain there, where other components will be placed above and below it.
Any ideas on how to achieve this?
UPDATE: in the attached sketch, the browser border appears in black and the scrollbars where they should ideally be appear in green. There is a container div in the middle of the page that contains the table in red. The table's headers should be sticky and the table shouldn't appear beyond the container div which acts as an aesthetic wrapper around it. Ideally, the browser vertical scrollbar would scroll the whole page down while leaving the page header (title + subtitle) and the table headers sticky. Also, when horizontally scrolling, the table should scroll within the container div. This is why I marked the parts that should not ideally appear in dashed lines.
All the changes we need to make are on demo.js
Firstly, we need to use a custom MUI TableContainer as the containerComponent for your #devexpress/dx-react-grid-material-ui Table. Basically, the purpose of this is so we can remove the overflow properties of the Table so that the scrolling is primarily for the body to address the requirement of
the scrollbars (horizontal and vertical) to appear at the edges of the
browser page, bottom and right respectively
import TableContainer from "#material-ui/core/TableContainer";
import makeStyles from "#material-ui/core/styles/makeStyles";
const useStyles = makeStyles({
tableContainer: {
overflow: "initial"
}
});
const MUITableContainer = ({ children, ...rest }) => {
const classes = useStyles();
return (
<TableContainer classes={{ root: classes.tableContainer }} {...rest}>
{children}
</TableContainer>
);
};
Secondly, at your MUITableContainer, get rid of the height: 400px so that the table's height will respond to the content. Again, the browser body bottom & right scrollbars will now control the document's scroll positions - this includes the table. Take a look at the Table containerComponent prop as well - we have assigned the custom TableContainer we created earlier.
<Paper>
<Grid rows={rows} columns={columns} rootComponent={GridRoot}>
<Table
containerComponent={MUITableContainer}
tableComponent={StickyTable}
/>
...
Lastly, to test this requirement:
there will be other objects before and after it.
Just render sample components before & after the Paper component
I cannot see the design spec you have referenced, but going off the sample in the comment on the first answer, I think you are trying to keep the header and footer from going off the left edge of the viewport when the user scrolls. But using just CSS, no JavaScript.
I took the entirety of the HTML (only the HTML) from your original code at https://codesandbox.io/s/2n40y (specifically <div id="root">) and dropped that into a Codepen.
Then I added a few visual design styles from your example so it looks kinda close.
Then I added the following CSS to make the column headers sticky:
th {
position: -webkit-sticky;
position: sticky;
top: 0;
}
I dropped in the following HTML as the first child and last child of <div id="root">, though it really doesn't matter where they live as long as they are not in the table.
<div class="stuckHeaderFooter">
[...]
</div>
To keep those from scrolling off screen when I scroll to the right, I made them sticky to the left (for RTL content you would need to make it sticky to the right):
.stuckHeaderFooter {
position: -webkit-sticky;
position: sticky;
left: 0;
padding: 0 1em;
display: inline-block;
}
The padding just makes it look less ugly. The inline-block is there to keep the block-level elements from filling the entire document width, which would keep them from being properly sticky since they would be wider than the viewport. You will probably have to set a max-width using vw units, but without knowing your content, target sizes, etc., I cannot say what would be best.
Finally, you have to remove the inline height: 400px on the first <div> under the root (<div class="MuiPaper-root MuiPaper-elevation1 MuiPaper-rounded" style="height: 400px;">). If you cannot override it because something injects it, then this style will override it for you but it brittle without knowing what else may be going on:
#root > div {
height: auto !important;
}
CSS only, no JavaScript in this approach at all, which is what I think you wanted.
Pen: https://codepen.io/aardrian/pen/PoNMopM
Debug view: https://cdpn.io/aardrian/debug/PoNMopM
Update: 5 October 2020: Looking at the sketch provided with the question, it is important to note that the container that does the clipping is the one that gets the scrollbar. So your options for a CSS-only solution are limited:
Add a fake block to make a visible border on the right (I updated the pen to add one; look at #root::after for an example but you will still need JS to make sure that does not appear until the table starts to get covered).
Yeah, I ran out of ideas.
In conclusion, I don't believe there is a CSS-only solution here because of how clipped areas work.
You can achieve this by setting the height and width to be equal to the viewport:
<Paper style={{ height: "100vh", width: "100vw" }}>
Example modified: https://codesandbox.io/s/table-sticky-header-forked-l77is?file=/demo.js

Make elements same height with Angular Material + Flex

I have an app I'm building that has a basic layout with a page header, a sidebar, and a main content area. I'm using Angular Material (1.0.5) with Angular.js (1.5.0). I'm using Angular Material's flexbox layout directives for my application's layout.
My problem is that I'm using flex to extend the sidebar to the bottom of the page, but when I scroll on a page with many ng-repeated items, it stays the height of the window. I would like it to extend all the way to the bottom of the page itself, as far as the repeated items goes. I've tried several different ways using Angular Material's flex directives, however this is the best I've been able to do thus far. One option I could do that I'd like to avoid is to calculate the height it needs to be using JavaScript in a $timeout, but like I said, that would be my last choice. Another option I know is available is to make the content area scrollable so that the header and sidebar are always fixed there. I would do that, but the client dislikes that and said no. (hence, not an option)
I've put together a CodePen to reproduce the issue I'm having. This has got my layout pretty much identical to what my app has got for its layout at the moment.
Firs create a wrapper class and insert all the content inside the wrapper
.wrapper {
width: 100%;
height: 100%;
overflow-y: auto;
}
<body ng-app="my-app" layout="column">
<div class="wrapper" layout="column">
ADD ALL YOUR CONTENT HERE
</div>
</body>
And for your rows / header not to shrink, add flex-shrink: 0 to them
.header,
.row-item {
flex-shrink: 0;
}
Result:
http://codepen.io/retamalph/pen/GZYZJo?editors=1100

css layout for footer at bottom with dynamic ajax content changing height of page

[Update]
I actually compromised on this problem for now by foregoing the fixed footer design.
It seems that there is no problem with dynamic content moving the footer and resizing containers appropriately unless the footer is fixed to the browser bottom initially.
I hope others will eventually provide a great solution that encompasses the best of both worlds.
I spent all day trying to get the footer to move down the page to accommodate dynamically added (via ajax) content. I really need some pointers or links because I haven't found anything that helps.
Basically:
My site has some pages that begin with only a text box and a button so that the total height of the content area is only a few inches beneath the header area.
I don't have any problem getting the sticky footer working so that the footer appears at the bottom of the browser window even when there is very little content on screen.
That same css layout works fine for other pages that have content that extends beneath the browser window.
The catch:
The content has to be rendered and passed to the browser with the initial load.
The Problem:
Any content that is added to the page via AJAX after the initial load paints down the page correctly -- but the footer remains in its initial location.
Please tell me there is a fix for this.
I can't post the css until checking with my boss first - if possible - and if needed, I will later - but it's just a very basic version of the many sticky footer css solutions floating around the web.
Thanks.
Currently fixed similar situation with small jQuery and CSS, where parameter is footer div object (i.e. $("#mainfooter")):
function positionFooter(obj){
if ($("body").outerHeight(true) > $(window).height()) {
obj.css("position","relative");
} else {
obj.css("position","fixed");
obj.css("bottom","0px");
}
}
Bound this function to $(document).ready and $(window).resize.
If ajax call resizes body, this should be called also after content load.
It sounds like your footer is using display: fixed or similar. Try changing the container of your footer to:
bottom: 0;
display: block;
position: absolute;
That will ensure it appears right at the bottom of whatever container it sits within (I'm assuming the <body> tag). Your problem now becomes ensuring that it appears at the bottom of the screen rather than the bottom of your document, which starts of being much shorter. You could accomplish this in a couple of ways, but perhaps the easiest would be to set a minimum height on your AJAX content container:
min-height: 600px;
height: auto !important /* This is a hack to make IE6 fix itself to a set height */
height: 600px; /* IE6 will always follow whatever instruction appears last, even if !important is specified */
The other approach is since you're using a JavaScript library (I assume?) to grab the required content, perhaps you could also adjust the height of the AJAX content container or change the footer's CSS once that content has loaded?
Without any code it´s hard to tell what the problem might be.
However, I´m using a sticky footer as described here that works very well although I haven´t added ajax content in it. Browser resizing works just fine though.
Use include in PHP and call the footer after the dynamic content appears.
I'm not sure you are looking for this, but I am also facing the same problem before and same CSS, where my content overlaps on the footer when i call the ajax through jQuery method.
Now I found the solution: Just get the div height through jQuery and apply the height to the div where you are returning your results from ajax.
var obj = $("#viewcomm").height();
if($.browser.msie) {
$("#viewcomm").height(obj).css({cursor:"auto"});
}
where here viewcomm is div ID.
I solved same kind of problem with following code, where content is the id of div where php pages load and footer is the footer tag.
var footerAdjustId = setInterval(adjustFooter, 2000);
function adjustFooter(){
$("footer").css("marginTop", $("#content").height() - $(window).height());
clearInterval(footerAdjustId);
}

How can a URL fragment affect a CSS layout?

Compare these 3 URLs (look at the top navigation bar in each case):
http://fast.kirkdesigns.co.uk/blog
as above but with the url fragment #navigation
as above but with the url fragment #node-2655
Note, that the only difference is the URL fragment on the end.
The first two pages display absolutely fine (in Firefox at least). It's the third one where the problem lies. The fragment #node-2655 pushes the top navbar off the top of the screen. When you then scroll back up to the top of the page, the navbar has been cut in half. This happens when using any URL fragment that causes the navbar to be out of the initial viewport when the page is first loaded.
So, how can using a url fragment affect the css layout like this?!
THE SOLUTION:
as suggested below, removing the overflow: hidden on the container element that held the navbar fixed the problem. I'd love to understand why though!
Remove the overflow:hidden on #main in css_75afd7072eaf4096aaebf60674218e31.css
I'd say it's a rendering bug in FireFox as it's fine in Opera. There shouldn't be anyway an anchor would change the CSS like you say (unless you are using jQuery or something).
I am having this problem too, and think I can see what is happening.
The "column" block with the massive (5678 pixel) margin and padding makes that block very tall. In browsers other than Firefox, the positive and negative values cancel each other out, but FF really does make it that tall - kind of.
FF also knows the two cancel each other out, but seems to look at the 5678px padding and decides the column block is poking out the bottom of the #wrapper block. This is overflow - and with overflow set to auto on #wrapper, you see the true size of #wrapper with a scroll-bar down the side.
With overflow set to hidden, FF takes away the scrollbar, but still seems to scroll the contents of #wrapper so that the item the fragment points to is at the top of the page. This is normal behaviour for fragment links in scrollable blocks, but since there is no scrollbar, you cannot scroll the content back down again, hence it looks like the layout has been effected by the fragment.
So in short, I suspect that FF is operating an invisible scrollbar in this example. That could be considered a bug, but it is probably correct behaviour. Being able to scroll the content up and down inside a non-overflowed fixed-sized block using URL fragments, is a technique that can be used effectively to implement image "sliders" that work even in the absence of JavaScript.
Hope that helps. This has been puzzling me for years, and this explanation suddenly struck me out the blue. My current workaround for this is to use jQuery "scroll to" plugin to scroll the whole page down to the fragment, as this seems to prevent the contents of #wrapper from scrolling internally.
You can also take "display: hidden" off #wrapper, but your page then ends up half a mile long.
I'll just point out that there may be some weird inheritance from the 30+ stylesheets linked to in the head. There may not, either, and it's probably a rendering bug (possibly related to :target styling) that Dan suggested. I just felt it worth pointing out that if you've got more than thirty stylesheets, you likely to start seeing some weirdness, whatever else might happens.
The reason is the column with the large padding has expanded it's container, but the expansion is then hidden but overflow:hidden; but with the use of the fragment it is being scrolled into the position of the fragment, effectively chopping off anything above that. You can use javascript and set scrollTop to 0 and it scroll it back to the normal position.
Basically a wierd edge case which browsers do not seem to handle very well.
Sorry this isn't an "answer," tho it is a response to the other comments here. This problem is just flabbergasting. It is very easy to isolate (i.e., has nothing to do with number of stylesheets), and doesn't have a proper "solution," as there is no way to achieve the desired rendering.
<!DOCTYPE html>
<html>
<head>
<style>
#container {
margin: 1em auto;
width: 40em;
}
#wrapper {
overflow: hidden;
position: relative;
}
#c1 {background-color: #aaf;}
#c2 {background-color: #ccf;}
.column {
float: left;
margin-bottom: -5678px;
padding-bottom: 5678px;
width: 50%;
}
#footer {
background-color: #eee;
padding: 1px;
text-align: center;
}
p {margin: 1em;}
</style>
</head>
<body>
<div id="container">
<div id="wrapper">
<div id="c1" class="column">
<p>This is some content in a short column. We would need some Javascript to change its height if we wanted a different background color for each column to stretch the full height of the respective columns...or we can use large padding together with an equal negative margin.</p>
<ul>
<li>Jump to P1</li>
<li>Jump to P2</li>
<li>Jump to P3</li>
</ul>
</div>
<div id="c2" class="column">
<p id="p1">The desired effect is to have the height of the two columns appear the same. We use 'overflow:hidden' on the containing div (#wrapper) to wrap it around the floated columns.</p>
<p id="p2">These paragraphs have fragment identifiers. Problem comes in when clicking one of the links on the left. Instead of scrolling just the page, the browser scrolls the div with 'overflow:hidden' so the target is at the top. It does this even if the target is already visible.</p>
<p id="p3">Opera does not exhibit this behavior. This occurs in Chrome/Safari, Firefox, and IE. (Interestingly, IE also works as expected if we completely remove the DOCTYPE declaration.)</p>
</div>
</div>
<div id="footer">
<p>Footer stuff.</p>
<p>To see why 'overflow: hidden' (or any other piece of the CSS) is needed, just try disabling it.</p>
</div>
</div>
</body>
</html>
Just as a side-note, the above technique is generally used to provide flexible-width mulit-column layouts. This is probably becoming less important these days as fixed-width layouts are becoming a lot more comment - browsers are able to magnify the web page to see small text, and fixed-width makes it a lot easier to control the typography of a page, e.g. set the width (in ems) to display the ideal nine words per line regardless of what font size and magnification the user chooses.
Sorry if that does not sound like an answer, but it is basically suggesting to discard this old model and consider moving to fixed-width columns (which is a whole new subject).
I was able to solve this with some javascript to scroll the body to the position the overflow hidden element was scrolled to.
setTimeout(() => {
let intendedScroll = document.getElementById("fragmentfix").scrollTop;
document.getElementById("fragmentfix").scrollTop = 0;
window.scrollTo(0, intendedScroll);
}, 0)

Resources