Home > Enterprise >  horizontal scroll with 100% width on grid cell
horizontal scroll with 100% width on grid cell

Time:12-15

I want to have a css grid, inside each cell of the grid, I want a title with a maximum size of 100% of the width of the cell. If title is too long, i want to scroll.

This is how it looks currently with the correct scrolling behavior but with a fixed width on the long title. Instead of a fixed width, i want a width of 100% of the cell width (so the grey block should be as long as red box)

codePen: screenshot

* {
  margin: 0;
  padding: 0;
}

body {
  padding: 50px;
}

h2 {
  font-size: 2em;
  white-space: nowrap;
}

.grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  width: 800px;
  gap: 20px;
}

.box {
  background-color: #e74c3c;
  height: 30vh;
}

.title-wrapper {
  background-color: #bdc3c7;
  width: 300px;
  overflow-x: scroll;
}
<div class=grid>

  <div>
    <div >
      <h2>long title, i can scroll---------</h2>
    </div>

    <div ></div>
  </div>

  <div>
    <h2>Short title</h2>
    <div ></div>
  </div>

</div>

Does anyone have an idea to do that ?

NOTE: To make the code example simple, the .grid class has a width of 800px but in reality, it's width is defined by its parent on which i can not predict the width (i'm working on a react app and this code will implement a component used in multiple places with different sizes).

CodePudding user response:

If your grid potentially contains overflowing content, you cannot work with 1fr, here's why:

  • 1fr is just short for minmax(auto, 1fr).
  • minmax(a, b) becomes a (without any minmax) when a >= b is true.
  • So in your case your grid behaves as if you had defined it as grid-template-columns: auto 1fr;, because auto is larger than 1fr for your first column.

To fix that, you need to tell your grid that it isn't allowed to extend the cells when content becomes too wide.

Use minmax(0, 1fr) instead of 1fr:

* {
  margin: 0;
  padding: 0;
}

body {
  padding: 50px;
}

h2 {
  font-size: 2em;
  white-space: nowrap;
}

.grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  width: 800px;
  gap: 20px;
}

.box {
  background-color: #e74c3c;
  height: 30vh;
}

h2 {
  background-color: #bdc3c7;
  overflow-x: scroll;
}
<div class=grid>

  <div>
    <h2>long title, i can scroll------------------ - - - - ----</h2>
    <div ></div>
  </div>

  <div>
    <h2>Short title</h2>
    <div ></div>
  </div>

</div>

CodePudding user response:

As commented heres a possibility:

* {
  margin: 0;
  padding: 0;
}

body {
  padding: 50px;
}

h2 {
  font-size: 2em;
  
  white-space: nowrap;
}

.grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  width: 800px;
  gap: 20px;
}

.box {
  background-color: #e74c3c;
  height: 50vh;
  max-width: 400px;
}

.title-wrapper {
  background-color: #bdc3c7;
  width: 100%;
  overflow-x: scroll;
}
<div class=grid >

    <div>
    

      <div  >
          <div  >
        <h2>long title, i can scroll---------------------------------</h2>
      </div>
      </div>
    </div>

    <div>
    
      <div  >
          <h2>Short title</h2>
      </div>
    </div>

 </div>

CodePudding user response:

Seems to be hard without JavaScript, Dev his answers works, but it involves a fixed max-width.

I've got a solution with JavaScript that seems to work.

    /* Execute when the DOM is loaded, because otherwise the HTML elements might nog be in the DOM. */
    window.addEventListener( 'DOMContentLoaded', () => {

        generateGridItemsWidthVariable()

    } )

    /* Execute when the window is resized, because the width of the boxes might change. */
    window.addEventListener( 'resize', () => {

        generateGridItemsWidthVariable()

    } )

    /* Generate the variable for the grid items. */
    function generateGridItemsWidthVariable() {

        /* Select all the grid items and create an array to loop trough. */
        let gridItems = Array.from( document.getElementsByClassName( 'grid__item' ) )

        /* Loop trough the grid items. */
        gridItems.forEach( gridItem => {

            /* Reset the grid item width, because otherwise the item won't resize. */
            gridItem.style.setProperty( '--grid-item--width', '' )

            /* Get the width of the grid item. */
            let gridItemWidth = gridItem.clientWidth.toString()
            /* Set the width of the grid item as a CSS variable. */
            gridItem.style.setProperty( '--grid-item--width', gridItemWidth   'px' )

        } )

    }
    * {
        margin: 0;
        padding: 0;
    }

    body {
        padding: 50px;
    }

    h2 {
        font-size: 2em;
        white-space: nowrap;
    }

    .grid {
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        width: 100%;
        max-width: 800px;
        gap: 20px;
    }

    .grid__item {
        --grid-item--width: 10px;
    }

    .box {
        background-color: #e74c3c;
        height: 30vh;
    }

    .title-wrapper {
        background-color: #bdc3c7;
        width: 100%;
    }
    .title-wrapper h2 {
        max-width: var(--grid-item--width);
        overflow-x: scroll;
    }
<div class=grid >

    <div >
        <div  >
            <h2>long title, i can scroll-----------------------</h2>
        </div>

        <div  ></div>
    </div>

    <div >
        <h2>Short title</h2>
        <div  ></div>
    </div>

</div>

  • Related