Существует ли свойство CSS для «развернуть по вертикали, пока не вызовете прокрутку страницы / родительского элемента»?

#css

#css

Вопрос:

У меня есть большой компонент «намереваюсь занять большую часть экрана». Если содержимое внутри этого компонента слишком велико для компонента, я хочу, чтобы у компонента были свои собственные полосы прокрутки, я не хочу, чтобы страница или родительский элемент создавали свои собственные полосы прокрутки.

Лучшее, что у меня есть для этого, — использовать flexbox для родительского элемента для достижения этой цели:

(Открыть всю страницу)

 document.getElementById("button").addEventListener("click", (e) => {

  document.getElementById("something").classList.toggle("something-big");
}); 
 .parent {
  height: 300px;
  display: flex;
  flex-flow: column nowrap;
  justify-content: stretch;
  border: dashed 1px black;
}

.body {
  background-color: #ddf;
  flex: 1 0 200px;
  overflow-y: scroll;
}

.something-big {
  height: 800px;
}

.something {
  background-color: #bbf;
  border: solid 1px blue; 
}

.footer,
.header {
  background-color: pink;
} 
 <div class="parent">

  <div class="header"> header </div>

  <div class="body">
    body
    <div class="something" id="something"> something
      <button id="button"> click me</button>
    </div>
  </div>

  <div class="footer"> footer </div>

</div> 

Однако мне не очень нравится это решение.

Если я разрабатываю это как библиотеку для использования в другом месте (т.Е.. У меня есть контроль над .body компонентом, но не над компонентами .header .footer . или .parent ), тогда мне нужно указать им «Чтобы это работало, вам нужно сделать родительский гибкий контейнер».

Есть ли свойство, которое я могу применить к .body only, чтобы достичь той же функциональности?

Ответ №1:

В принципе, вы можете поиграть с:

  • max-height : процент ( 80vh = 80% of viewport height пример 🙂
  • height: auto , height: inherit;
  • overflow-y: scroll; , overflow: hidden;

Для оформления height каждого компонента и какого из scrolls них.

Проверьте элементы под комментариями в CSS :

 /* CHECK THIS */
 

Scrollig HTML-страница:

 .parent,
.parent > .body {
    height: auto;
}
 
 // Get the button
let myBtn = document.querySelector('#myBtn');

// A function to draw boxes (more content in .body > .something > HERE)
function drawBoxes(){
    // Array to hold HTMl output
    let output = [];

    // Get boxes container
    let boxesContainer = document.querySelector('.boxes');
    
    // Adding boxes for testing (You can play with that to check for smaller space (try 3 or 4 ))
    let boxesInTotal = 40;

    // Loop to draw the boxes
    for(let i = 0; i < boxesInTotal; i  ){
        let box = 
        `<div class="box"></div>`;
        output.push(box);
    }

    // Print the boxes
    boxesContainer.innerHTML = output.join('');
}


// Click on the button to see the changes
myBtn.addEventListener('click', () => {
    drawBoxes();
}); 
 *, *::after, *::before {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}


/* CHECK THIS */
.parent,
.parent > .body {
    height: auto;
}

.parent {
    background-color: rgb(24, 146, 173);
    width: 100%;
    padding: 20px;
    color: #FFFFFF;
    text-align: center;
}

.parent > body > h1,
.parent > h1 {
    margin-bottom: 20px;
}

.parent > .header {
    height: 100px;
    border: 1px solid #FFFFFF;
    padding: 20px;
    display: flex;
    justify-content: center;
    align-items: center;
}

.parent > .body {
    color: #FFFFFF;
    border: 1px solid #FFFFFF;
}

.parent > .body > #something > #myBtn {
    padding: 15px 20px;
    border-radius: 4px;
    background: #121212;
    color: #fafafa;
}

#something > .boxes {
    display: flex;
    flex-wrap: wrap;
    height: auto;
}

#something > .boxes > .box {
    border: 1px solid #FFFFFF;
    height: 300px;
    width: 300px;
    margin: 10px auto;
    display: block;
    background: red;
} 
 <div class="parent">
    <h1>Parent</h1>
    <div class="header">
        <h2>Header</h2>
    </div>
    <div class="body">
        <h1>Body</h1>
        <div id="something">
            <button id="myBtn">Click</button>
            <div class="boxes"></div>
        </div>
    </div>
</div> 

Scrolling .body:

 // Get the button
let myBtn = document.querySelector('#myBtn');

// A function to draw boxes (more content in .body > .something > HERE)
function drawBoxes(){
    // Array to hold HTMl output
    let output = [];

    // Get boxes container
    let boxesContainer = document.querySelector('.boxes');
    
    // Adding boxes for testing
    let boxesInTotal = 40;

    // Loop to draw the boxes
    for(let i = 0; i < boxesInTotal; i  ){
        let box = 
        `<div class="box"></div>`;
        output.push(box);
    }

    // Print the boxes
    boxesContainer.innerHTML = output.join('');
}


// Click on the button to see the changes
myBtn.addEventListener('click', () => {
    drawBoxes();
}); 
 *, *::after, *::before {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* CHECK THIS */
body {
    height: 2000px;
}

.parent {
    background-color: rgb(24, 146, 173);
    width: 100%;
    padding: 20px;
    color: #FFFFFF;
    text-align: center;
    height: auto;
}

.parent > body > h1,
.parent > h1 {
    margin-bottom: 20px;
}

.parent > .header {
    height: 100px;
    border: 1px solid #FFFFFF;
    padding: 20px;
    display: flex;
    justify-content: center;
    align-items: center;
}

/* CHECK THIS */
.parent > .body {
    color: #FFFFFF;
    border: 1px solid #FFFFFF;
    max-height: 70vh;
    overflow-y: scroll;
}
/* CHECK THIS */
.parent > .body > #something {
    height: inherit;
}


.parent > .body > #something > #myBtn {
    padding: 15px 20px;
    border-radius: 4px;
    background: #121212;
    color: #fafafa;
}

#something > .boxes {
    display: flex;
    flex-wrap: wrap;
}

#something > .boxes > .box {
    border: 1px solid #FFFFFF;
    height: 300px;
    width: 300px;
    margin: 10px auto;
    display: block;
    background: red;
} 
 <div class="parent">
    <h1>Parent</h1>
    <div class="header">
        <h2>Header</h2>
    </div>
    <div class="body">
        <h1>Body</h1>
        <div id="something">
            <button id="myBtn">Click</button>
            <div class="boxes"></div>
        </div>
    </div>
</div> 

Прокрутка .parent:

 // Get the button
let myBtn = document.querySelector('#myBtn');

// A function to draw boxes (more content in .body > .something > HERE)
function drawBoxes(){
    // Array to hold HTMl output
    let output = [];

    // Get boxes container
    let boxesContainer = document.querySelector('.boxes');
    
    // Adding boxes for testing
    let boxesInTotal = 40;

    // Loop to draw the boxes
    for(let i = 0; i < boxesInTotal; i  ){
        let box = 
        `<div class="box"></div>`;
        output.push(box);
    }

    // Print the boxes
    boxesContainer.innerHTML = output.join('');
}


// Click on the button to see the changes
myBtn.addEventListener('click', () => {
    drawBoxes();
}); 
 *, *::after, *::before {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* CHECK THIS */
.parent {
    background-color: rgb(24, 146, 173);
    width: 100%;
    padding: 20px;
    color: #FFFFFF;
    text-align: center;
    max-height: 90vh;
    overflow-y: scroll;
}

.parent > body > h1,
.parent > h1 {
    margin-bottom: 20px;
}

.parent > .header {
    height: 100px;
    border: 1px solid #FFFFFF;
    padding: 20px;
    display: flex;
    justify-content: center;
    align-items: center;
}

.parent > .body {
    color: #FFFFFF;
    border: 1px solid #FFFFFF;
}

.parent > .body > #something > #myBtn {
    padding: 15px 20px;
    border-radius: 4px;
    background: #121212;
    color: #fafafa;
}

#something > .boxes {
    display: flex;
    flex-wrap: wrap;
}

#something > .boxes > .box {
    border: 1px solid #FFFFFF;
    height: 300px;
    width: 300px;
    margin: 10px auto;
    display: block;
    background: red;
} 
 <div class="parent">
    <h1>Parent</h1>
    <div class="header">
        <h2>Header</h2>
    </div>
    <div class="body">
        <h1>Body</h1>
        <div id="something">
            <button id="myBtn">Click</button>
            <div class="boxes"></div>
        </div>
    </div>
</div> 

Scrolling #something:

 // Get the button
let myBtn = document.querySelector('#myBtn');

// A function to draw boxes (more content in .body > .something > HERE)
function drawBoxes(){
    // Array to hold HTMl output
    let output = [];

    // Get boxes container
    let boxesContainer = document.querySelector('.boxes');
    
    // Adding boxes for testing
    let boxesInTotal = 40;

    // Loop to draw the boxes
    for(let i = 0; i < boxesInTotal; i  ){
        let box = 
        `<div class="box"></div>`;
        output.push(box);
    }

    // Print the boxes
    boxesContainer.innerHTML = output.join('');
}


// Click on the button to see the changes
myBtn.addEventListener('click', () => {
    drawBoxes();
}); 
 *, *::after, *::before {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* CHECK THIS */
.parent {
    background-color: rgb(24, 146, 173);
    width: 100%;
    padding: 20px;
    color: #FFFFFF;
    text-align: center;
    height: auto;
}

.parent > body > h1,
.parent > h1 {
    margin-bottom: 20px;
}

.parent > .header {
    height: 100px;
    border: 1px solid #FFFFFF;
    padding: 20px;
    display: flex;
    justify-content: center;
    align-items: center;
}

/* CHECK THIS */
.parent > .body {
    color: #FFFFFF;
    border: 1px solid #FFFFFF;
    max-height: 70vh;
    overflow: hidden;
}

/* CHECK THIS */
.parent > .body > #something {
    max-height: inherit;
    overflow-y: scroll;
}

.parent > .body > #something > #myBtn {
    padding: 15px 20px;
    border-radius: 4px;
    background: #121212;
    color: #fafafa;
}

#something > .boxes {
    display: flex;
    flex-wrap: wrap;
}

#something > .boxes > .box {
    border: 1px solid #FFFFFF;
    height: 300px;
    width: 300px;
    margin: 10px auto;
    display: block;
    background: red;
} 
 <div class="parent">
    <h1>Parent</h1>
    <div class="header">
        <h2>Header</h2>
    </div>
    <div class="body">
        <h1>Body</h1>
        <div id="something">
            <button id="myBtn">Click</button>
            <div class="boxes"></div>
        </div>
    </div>
</div> 

Комментарии:

1. Конечно, поэтому я думаю, что использование vh здесь довольно разумно, где в основном это своего рода оценка, где вы бы сказали: «Мы считаем, что этот компонент должен занимать около 70% вертикальной высоты страницы» — если после этого компонента есть дополнительный контент, то, конечно, он начнетпрокрутка. Предположительно, тогда пользователь компонента должен переопределить это значение vh в соответствии с требованиями.