Search code examples
cssreactjsflexboxcss-gridsplitpane

react split pane shows above other components when using `display: flex`


For my new react project I need a split pane.
I am using https://github.com/tomkp/react-split-pane for this.
After I implemented everything, I wanted to my header above so it would look like this.

How the design should look like


So I added the header to my root component.

render() {
        return (
            <div className='App'>
                <h1>This is my heading</h1>
                <SplitPane split='vertical' minSize={50} defaultSize={100}>
                    <div>split 1</div>
                    <div>split 2</div>
                </SplitPane>
            </div>
        );
    }
}

Just like this without any css it gave me nearly a correct result. And the only problem here is that the split pane seems to take 100vh as its height and therefore the overall application is bigger. Which gives me the nice scroll bar, which I don't want.

Wihtout any css

My next idea was to just put everything into css grid (I know that it probably isn't the best use case but at least I would know there how to solve the sizing problem) and then resize it using the relative units.

The css I added to my main component is.

.App {
    display: grid;
    grid-template-rows: auto 1fr;
}

This change didn't get me the effect I wanted it to. Instead of neatly stacking everything it somehow put the split pane above the header.

image with css applied

I thought that I did something wrong with css grid, so I applied display: flex; which gave me the same problem.


I don't really know what the problem here is, so I'm curious if anybody had encountered such a problem before.


Solution

  • SplitPane source code


    Add this to your .App selector:

    .App {
        position: relative;
    }
    

    Also, if you want the widths of both panes to be exactly half, change your SplitPane component to this:

    <SplitPane split="vertical" minSize="50%" defaultSize="50%">
    

    Unfortunately, there is a problem where the panes stops resizing and the application goes out of bounds at very small widths.


    In response to:

    SplitPane shrinking down to a size where it's not really usable even though the height is set to 100%.

    Content inside SplitPane is not visible/usable because:

    1. SplitPane has the property height: 100%. This means SplitPane's height is 100% of its parent's height.


    2. SplitPane has the property overflow: hidden. This will hide any content that exceeds SplitPane's dimensions.

      Since SplitPane's height = .App's height = h1's height and the height for h1 was about 30-40px, SplitPane's height was also about 30-40px. This meant any child of SplitPane with a height greater than 30-40px had its content cut off.


    3. SplitPane is most likely calculating how much to offset itself from the top by calculating the total height of its preceding siblings.


    So, now we know SplitPane's CSS properties look like this:

    {
        position: absolute;
        top: 0 || /* auto-calculated by SplitPane */;
        left: 0 || /* auto-calculated by SplitPane */;
        overflow: hidden;
        height: 100%; /* total height of preceding siblings */
        ...
    }
    


    Your next steps would be to decide on how you would like your application to look and function and make choices based on your decision. To start:

    • Do you want your navigation bar fixed to the top of the viewport?

    • How would you like to handle excess content inside of the panes if you don't want a scroll bar?

    • Is your website mobile-friendly? If so, how would you like to display the split panes on small screens?


    In response to:

    How do I change to position: relative while assigning all space below the header to the split view?

    Some possible solutions would be to use Javascript or possibly Sass/SCSS/Less to set the total height of SplitPane equal to the viewport's height minus how much SplitPane was offset from the top.

    It is hard to give a definitive answer because I do not know how you want to handle viewing content that exceeds 100vh without a scroll bar.


    In response to:

    [I] can't use display: grid or flex since it would still overwrite the header.

    Flexbox/Grid isn't working because SplitPane isn't living in the same space as its siblings. You'd have to overwrite SplitPane's position property to static.

    CodePen

    .App {
      display: flex; /* Introduce Flexbox */
    
      /* This is added to change the orientation of elements from 
         left-right (row) to top-bottom (column). */
      flex-direction: column;
    }
    
    <SplitPane ... style={{ position: "static" }}>
    

    Next steps

    The only thing I can recommend at this stage is to add height: 100vh and width: 100vw to .App.