Nicolas
Nicolas

Reputation: 2376

Text remains wrapped inside it's parent div - CSS, React

The question is pretty straight-forward and I have read lots and lots of posts about the same issue, though in my specific case all these solutions are not working because I am probably handling it wrong or making it over-complicated.

Some of the solutions I tried:

Most of these posts come to the conclusion that you should use inline-block in combination with white-space: nowrap. Though after numerous trial and error tries, I actually kinda forgot what I did and did not try..

My specific case

I have a React application in which I want to display an hours-bar. This bar has a (sort-of) table layout but just with 1 row. The bar consists out of 15 cells (div's).

The problem

Each cell should have a specific text above it when a certain condition is met. So for example, I want to show a text value on the starting cell div, and the ending cell div and then each 5th cell again. It should look something like this:

enter image description here

I figured I could achieve this by making a 'Time' row inside the body of the time bar, however when I add it as a separate row, then the times / text will never be above the correct cells when the bar has multiple lines on the screen, you would then get something like this:

enter image description here

So my next idea was to make 2 separate div's inside the row where 1 div (the top div) functions as the header and the second div functions as the actual bar:

<TimeColumnBody>        
    <TimeColumnHeader>
        {(() => {
            if (item.showtime === true)
            {
                return <Test>{item.name}</Test>
            }
        })()}
    </TimeColumnHeader>
    <TimeColumn
        key={item.key} 
        name={item.name}
    >
    </TimeColumn>
</TimeColumnBody>

The above html get's rendered on each separate cell (time-step), so with the above example that would be 15 times (8:00 to 11:30 with steps of 15 minutes).

The objects TimeColumnBody, TimeColumnHeader and TimeColumn are created inside the react file and they are simple custom div elements with styling (using styled-components) :

const TimeColumnBody = styled.div`
    float: left;
    width: 100%;
    height: 100%;
    @media only screen and (min-width: 768px) {
        width: ${props => (props.span ? props.span / 44 * 100 : "2.27")}%;
        height: 100%;
    }
`;

const TimeColumnHeader = styled.div`
    display: flex;
    align-items: flex-end;
    height: 50%;
    background-color: blue;
    color: white;
    white-space: nowrap;
`;

const TimeColumn = styled.div`
    height: 50%;
    background-color: red;
`;

The creating of the entire table / time-bar happens in the React render part:

render() {
        return (
                <TimeContainer>
                    <TimeRow>
                        {this.renderTimeTable()}
                    </TimeRow>
                </TimeContainer>
        );      
    }

The renderTimeTable function is the part where the cells are being created (TimeColumnBody, TimeColumnHeader, TimeColumn elements).

The text inside the TimeColumnHeader div remains wrapped inside the div even with the white-space: nowrap; property:

enter image description here

I tried adding the white-space: nowrap; property to the TimeColumn div with no effect, then I added the display: inline-block property with no effect, then I tried adding it to some parent div's but also without result.

The entire styling looks (currently) as follows (style added inline for easier reading):

<div class="App" style="text-align: center; height: 100%; overflow: auto;">
    <div class="Nav-LeftPane" style="width: 15%; height: 100%; position: fixed; box-sizing: border-box; overflow-y: auto; float: left;">...</div>
    <div class="content" style="width: 85%; height: 100%; text-align: center; overflow: hidden; float: right;">
        <div class="content-timebar" style="padding-left: 1%; padding-right: 1%; padding-top: 3%; height: 100%;">
            <!-- The actual Time Bar : --> 
            <div class="TimeContainer" style="width: 100%; height: 10%;">
                <div class="TimeRow" style="height: 100%;"> <!-- This div also has some :after logic: .TimeRow::after { content: ""; clear: both; display: table; } -->
                    <!-- the cell part which gets generated 15 times -->
                    <div class="TimeColumnBody" style="width: 2.222%; height: 100%; float: left;">
                        <div class="TimeColumnHeader" style="display: flex; align-items: flex-end; height: 50%; background-color: blue; color: white; white-space: nowrap;">
                            08:00
                        </div>
                        <div class="TimeColumn" style="height: 50%; background-color: red;"></div>
                    </div>
                </div>
            </div>

        </div>
    </div>
</div>

I am now out of ideas and hope someone has a (better) solution to acheive this.

UPDATE

Added a CodePen: https://codepen.io/anon/pen/rqJgRx

Upvotes: 2

Views: 947

Answers (1)

Toby
Toby

Reputation: 13385

The problem initially appears to be related to overflow or wrapping, but it is actually a z-index issue - because you are floating .TimeColumnBody left, each subsequent element has a higher z-index than the last and thus overlaps the previous item. I was able to fix this simply by adding a span to the first time with:

.TimeColumnHeader span {
   position: absolute;
}

See pen: https://codepen.io/anon/pen/NOyZOx

Upvotes: 1

Related Questions