How to add margin without adding additional space to parent div - css

I create a sidebar drawer using react material ui and try to create the clicked item on the sidebar drawer style to be like in this example http://react-material-dashboard.devias.io/dashboard.
I use the code from here https://github.com/mui-org/material-ui/blob/master/docs/src/pages/demos/drawers/ResponsiveDrawer.js to create the drawer.
And add style like this for the active item.
const styles = () => ({
clickedItem: {
borderLeft: "4px solid #0767DB",
borderRadius: "4px",
backgroundColor: "#F6F9FD",
marginLeft: "10px"
}
});
However, because of I add the marginLeft, the sidebar is now scrollable in x axis because it adds additional space on the right side. I want it to add margin of left without affecting the right side. I try to use overflow: "hidden". But, the y scroll bar is also hide and can't be scroll.
How to fix it so the item size (width) is still the same even though I add marginLeft?

I had a play with the browser-inspect on the dashboard linked.
Try adding: width:auto; to the styles you're passing the active element. This will stop the margin being added to the fixed width indiscriminately and causing the overflow.
Just as a bonus, it might help to add word-break: break-all; to avoid any singular long words also causing an overflow in the drawer.
Hope this helps!

Related

Is there a way to make the height of a Drawer's child responsive using Material-UI?

A little bit of context: I'm using a temporary drawer from Material-UI with anchor="right". Inside it I have a div as a container of a multi-step form. For the first step of the form the content is smaller than the height of the screen (in this case I want the div to be displayed as 100% of the parent which is the drawer), but for the next 2 steps the content is greater than the height of the screen. In those cases I want to have scrollable content.
My actual problem: I figured out how to have either full height of the drawer (for the first step) or scrollable content (for the other 2 steps) but I need to have them all together. The div containing the form has a different color from the drawer's color (hence why I need those 2 cases working together).
My problem is more related to CSS than Material-UI I suppose.
Here's what I tried so far (using makeStyles from Material-UI):
//v1
container: {
height: '100%',
}
//v2
container: {
minHeight: '100vh',
}
//v3
container: {
minHeight: '200vh'
}
It appears that using the third variant it works for now but I'm aware that in the future I might have more content that exceeds that value resulting in the same problem.
Material-UI version: "#material-ui/core": "^4.11.3" (even thought I don't think it's relevant).

"clearfix" for position fixed

disclaimer: I know that fixed elements are not ment to take theire own space in the flow of a page but i think i need it anyway.
Question:
I try to have my nav in a Grid which has the height of 100vh When I press the trigger element the whole grid slides to the side and reveals the Navigation by adding a class with js. I want the whole viewport container to be in a fixed position but as I set it to position: fixed; all of the content below will overflow the container as it should by default behavior.
is there a way to "clearfix" this overflow?
I aswell want to hide it again with a "onscroll" event, so just changing the backgroundcolor is no option for me.
One way could be to change the overflow permission in the container with something like:
someDiv{
<!---Your nav should be wrapped with this-->
position: fixed;
overflow: hidden !important;
}
Then, add an onClick to your nav so when the nav is accessed, the overflow is changed
document.getElementById('someDiv').onclick = function(){
document.getElementById('someDiv').style.overflow = 'visible';
}
Not quite sure if this is what you are after.

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

center placeholder of type span

I have created a span which acts as a placeholder for figcaption. I am trying to center the placeholder but it is creating some padding(not sure) which I cannot control.
Here is the link for code sandbox.
sanbox
I have tried commenting out property width:0 which indeed centered the caption but the focus is misbehaving now.
This is the react component for span which acts as placeholder
<span
contentEditable={false}
style={{
pointerEvents: "none",
display: "inline-block",
width: "0",
maxWidth: "100%",
whiteSpace: "nowrap",
opacity: "0.333"
}}
>
Figure Caption
</span>
To reproduce the bug, please open the sandbox, place your cursor inside editor, and click on insert image button. As soon as you click it an image with caption gets inserted. Placeholder inside it is not centered.
Just remove width: "0" from settings. In a centered parent and child, the width:0 for a block (or inline-block) child element, puts it in the center of parent (in fact it puts the left of element in the center of parent) and if it contains text or any type of content, the content will grow to the right (The content overflows the zero-width element).
To overcome the focus problem there are some workarounds:
First Idea: using margin-left. You may still use width:0 but you have to set margin-left equal to half width of caption text. This idea needs more coding to calculate the dynamic width of caption as soon as text changes (onKeyup event).
Another Idea: Remove the width:0 but: Hide the default caption as soon as user clicks on the cpation and set it back again if the user input was null. You may hold the default caption in a data-caption tag to recover it easily.

Visible overflow in one direction with scrolling in the other direction

I need to have absolutely positioned element which scrolls with its parent. The absolutely positioned element may be wider than the scrollable container, in which case the content is currently being clipped. It appears that combining overflow-y: auto; and overflow-x: visible; does not work.
Here is a JSFiddle to illustrate the problem. Notice the popups cause horizontal scrolling.
And this is what it should look like here, only with scrolling.
Can this be accomplished through CSS?
You have a hard coded width. The <div> will automatically take the full width of the page, so you want to do is restrict the maximum width that the div can contain so change the width: 400px to something like max-width: 90%
Here's a JSFiddle example: http://jsfiddle.net/c8DdL/3/
For posterity: The problem does require a JavaScript solution. Ultimately the project feature I was working on was changed to avoid this problem and resulted in a better design.
use max_width instead of width 400. That is the only solution.
I found a solution in my project, by hiding the horizontal scrollbar (I use a custom scrollbar ui), giving the container a padding-right of 300px and a margin-right of -300px. The padding and -margin make it so the normal children are aligned the same, except there's also extra room in the container in case an absolutely-positioned element extends out of that zone. (scrollable areas cut off anything outside the outer bounds)
Of course, if you have content to the right of the scroll area, this makes it extend out onto it. With a transparent background that isn't a visual problem; however it then blocks mouse events.
To solve that, I added two elements as siblings of the scroll-view, like so:
// this outer container resizes to match the size of scrollContainer
<div style={{position: "relative"}>
<div id="scrollContainer" style={{paddingRight: 300, marginRight: -300}}>
// stuff which might extend to the right
</div>
// the containers below resize with the outer container
// however, notice that the 2nd one is positioned only over the possibly-extended-onto area
<div id="insideArea" style={{position: "absolute", left: 0, right: 0, top: 0, bottom: 0}}
onMouseEnter={()=> {
// we're back inside, so enable scroll-container mouse-events
$("scrollContainer").css("pointer-events", "auto");
// prevent self from blocking mouse events for scrollContainer
$("insideArea").css("display", "none");
// re-enable extend-area div, so we know when mouse moves over it
$("extendArea").css("display", "block");
}/>
<div id="extendArea" style={{position: "absolute", top: 0, bottom: 0, left: "100%", width: 300}}
onMouseEnter={()=> {
// we're over the extend-area, so disable scroll-container mouse events
$("scrollContainer").css("pointer-events", "none");
// prevent self from blocking mouse events for behind-extend-area elements
$("#extendArea").css("display", "none");
// re-enable inside-area div, so we know when mouse moves over it
$("#insideArea").css("display", "block");
}/>
What does the above do? It makes it so when your mouse enters the normal scroll-view area, pointer-events are enabled, letting you click on stuff inside -- but when your mouse moves into the special "extended" area, the scroll-view mouse-events are disabled, letting you click on the normal items behind that area.
This solution will probably never be used by anyone else, but I spent enough time finding it I thought I'd share it anyway!

Resources