How to make one element shrink while two other elements stay the same

How to make one element shrink while two other elements stay the same
javascript
Ethan Jackson

async function main() { const numStudents = Number(await new Modal('a\n\na\n\na\n\na\n\na\n\na', 'info', 'How many students do you have?', 'Cancel', 'Submit').response()); const numGrades = Number(await new Modal('', 'info', 'How many grades does each student have?', 'Cancel', 'Submit').response()); } class Modal { constructor(bodyText, type = 'info', headerText = null, footerText = 'Close', prompt = null, closeable = true) { this.type = type; if (headerText === null) { switch (this.type) { case 'success': this.headerText = 'Success!'; break; case 'info': this.headerText = 'Information'; break; case 'warning': this.headerText = 'Warning!' break; case 'error': this.headerText = 'An error has occurred'; break; default: this.headerText = 'Notification'; } } else { this.headerText = headerText; } this.bodyText = bodyText; this.footerText = footerText; this.closeable = closeable; this.prompt = prompt; this.create(); this.open(); } create() { this.dialog = document.createElement('dialog'); const header = document.createElement('header'); header.classList.add(this.type, 'background'); if (this.closeable) { const closeButton = document.createElement('button'); closeButton.classList.add('close'); closeButton.innerText = '×'; header.appendChild(closeButton); } const headerText = document.createElement('h3'); headerText.innerText = this.headerText; header.appendChild(headerText); this.dialog.appendChild(header); const form = document.createElement('form'); form.method = 'dialog'; const body = document.createElement('main'); this.bodyText.split('\n\n').forEach((paragraph) => { const p = document.createElement('p'); p.innerText = paragraph; body.appendChild(p); }); if (this.prompt !== null) { this.input = document.createElement('input'); this.input.placeholder = ' '; this.input.autofocus = true; const p = document.createElement('p'); p.appendChild(this.input); body.appendChild(p); } form.appendChild(body); const footer = document.createElement('footer'); footer.classList.add(this.type, 'text'); const hiddenSubmitButton = document.createElement('button'); hiddenSubmitButton.value = 'submit'; hiddenSubmitButton.hidden = true; footer.appendChild(hiddenSubmitButton); const closeButton = document.createElement('button'); closeButton.classList.add(this.type, 'text', 'animated'); closeButton.innerText = this.footerText; footer.appendChild(closeButton); if (this.prompt === null) { closeButton.autofocus = true; } else { const submitButton = document.createElement('button'); submitButton.classList.add(this.type, 'background', 'animated'); submitButton.innerText = this.prompt; submitButton.value = 'submit'; footer.appendChild(submitButton); } form.appendChild(footer); this.dialog.addEventListener('close', (event) => { this.close(event.target.returnValue); }); this.dialog.appendChild(form); document.body.appendChild(this.dialog); } open() { this.dialog.showModal(); } close(returnValue) { if (this.prompt !== null) { if (returnValue === '') { this.responseValue = null; if (this.rejectPromise !== undefined) { this.rejectPromise('User canceled prompt'); } } else { this.responseValue = this.input.value; if (this.rejectPromise !== undefined) { this.resolvePromise(this.responseValue); } } } } response() { this.promise = new Promise((resolve, reject) => { if (this.responseValue !== undefined) { if (this.responseValue === null) { reject('User canceled prompt') } else { resolve(this.responseValue); } } else { this.resolvePromise = resolve; this.rejectPromise = reject; } }); return this.promise; } } main();
:root { --error: #c00; --error-dark: #900; --error-light: #f00; --info: #36c; --info-dark: #039; --info-light: #69f; --muted: #ddd; --muted-dark: #888; --muted-light: #eee; --success: #0c0; --success-dark: #090; --success-light: #0f0; --warning: #cc0; --warning-dark: #990; --warning-light: #ff0; } body { font-family: Arial, Helvetica, sans-serif; } button { border: 2px solid; border-radius: 10px; cursor: pointer; margin: 1em 0.5em; padding: 10px 15px; transition: transform 1s; } button:active { transform: scale(90%); } button.animated { background-color: transparent; overflow: hidden; position: relative; transition: color 0.3s, border-color 0.3s, transform 0.2s; z-index: 1; } button.animated:hover { border-color: transparent; } button.animated::after { border: 0; border-radius: 50%; content: ""; height: 200%; left: -50%; opacity: 0; position: absolute; transform: scale(0.1); transform-origin: center; transition: opacity 0.3s, transform 0.3s; top: -50%; width: 200%; z-index: -1; } button.animated:hover::after { opacity: 1; transform: scale(1); } input { border: 0; font: inherit; letter-spacing: normal; margin: 0; padding: 0; } input:focus, input:placeholder-shown { box-shadow: 0 2px 0 var(--muted); outline: none; } dialog { background-color: white; border: 0; border-radius: 10px; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); opacity: 0; outline: none; padding: 0; transform: scale(0); transition: all 0.4s allow-discrete; width: 50%; } dialog:open { opacity: 1; transform: scale(1); } @starting-style { dialog:open { opacity: 0; transform: scale(0); } } dialog::backdrop { background-color: rgba(0, 0, 0, 0); transition: all 0.4s allow-discrete; } dialog:open::backdrop { background-color: rgba(0, 0, 0, 0.4); } @starting-style { dialog:open::backdrop { background-color: rgba(0, 0, 0, 0); } } dialog header, dialog main, dialog footer { display: flow-root; padding: 0 1em; text-align: center; } dialog header { background-color: black; color: white; } dialog main, dialog footer { background-color: white; color: black; } dialog form { display: flex; flex-direction: column; } dialog header, dialog footer { flex: initial; } dialog main { flex: 1 1 auto; overflow-y: auto; } .close { aspect-ratio: 1 / 1; background-color: rgba(0, 0, 0, 0); border: 0; border-radius: 50%; box-sizing: border-box; color: var(--muted); font-size: 1.2em; font-weight: bold; height: 1.2em; margin: 0; padding: 0; position: absolute; right: 0.5rem; top: 0.5rem; user-select: none; } .close:hover, .close:focus { background-color: rgba(255, 255, 255, 0.2); color: white; } .success.text, .info.text, .warning.text, .error.text, button.animated.success.background::after, button.animated.info.background::after, button.animated.warning.background::after, button.animated.error.background::after { background-color: white; } .success.background, .info.background, warning.background, error.background, button.animated.success.text:hover, button.animated.info.text:hover, button.animated.warning.text:hover, button.animated.error.text:hover { color: white; } button.animated.success.text, button.animated.info.text, button.animated.warning.text, button.animated.error.text { border-color: var(--muted); } .success.text, button.animated.success.background:hover { color: var(--success); } .success.background, button.animated.success.text::after { background-color: var(--success); } button.animated.success.text:hover, button.animated.success.background { border-color: var(--success); } .info.text, button.animated.info.background:hover { color: var(--info); } .info.background, button.animated.info.text::after { background-color: var(--info); } button.animated.info.text:hover, button.animated.info.background { border-color: var(--info); } .warning.text, button.animated.warning.background:hover { color: var(--warning); } .warning.background, button.animated.warning.text::after { background-color: var(--warning); } button.animated.warning.text:hover, button.animated.warning.background { border-color: var(--warning); } .error.text, button.animated.error.background:hover { color: var(--error); } .error.background, button.animated.error.text::after { background-color: var(--error); } button.animated.error.text:hover, button.animated.error.background { border-color: var(--error); }

I have a modal, as you can easily see in the link. When you resize the window until a scroll bar appears, you will see that the scroll bar appears for the entire modal. If you look closely, you can observe that the modal consists of a header (obviously), a main (the body text), and a footer (the button(s) at the bottom). I want the header and footer to act like a header and footer by only having the main portion have a scroll bar. How do I do this?

Answer

Since your grid is mainly a column layout , you may use grid instead flex and set the rows to auto and 1fr for the one supposed to fill the remaining space and scroll if needed.

Below a snippet with a couple of grid and overflow rules to make main scroll:

async function main() { const numStudents = Number(await new Modal('a\n\na\n\na\n\na\n\na\n\na', 'info', 'How many students do you have?', 'Cancel', 'Submit').response()); const numGrades = Number(await new Modal('', 'info', 'How many grades does each student have?', 'Cancel', 'Submit').response()); } class Modal { constructor(bodyText, type = 'info', headerText = null, footerText = 'Close', prompt = null, closeable = true) { this.type = type; if (headerText === null) { switch (this.type) { case 'success': this.headerText = 'Success!'; break; case 'info': this.headerText = 'Information'; break; case 'warning': this.headerText = 'Warning!' break; case 'error': this.headerText = 'An error has occurred'; break; default: this.headerText = 'Notification'; } } else { this.headerText = headerText; } this.bodyText = bodyText; this.footerText = footerText; this.closeable = closeable; this.prompt = prompt; this.create(); this.open(); } create() { this.dialog = document.createElement('dialog'); const header = document.createElement('header'); header.classList.add(this.type, 'background'); if (this.closeable) { const closeButton = document.createElement('button'); closeButton.classList.add('close'); closeButton.innerText = '×'; header.appendChild(closeButton); } const headerText = document.createElement('h3'); headerText.innerText = this.headerText; header.appendChild(headerText); this.dialog.appendChild(header); const form = document.createElement('form'); form.method = 'dialog'; const body = document.createElement('main'); this.bodyText.split('\n\n').forEach((paragraph) => { const p = document.createElement('p'); p.innerText = paragraph; body.appendChild(p); }); if (this.prompt !== null) { this.input = document.createElement('input'); this.input.placeholder = ' '; this.input.autofocus = true; const p = document.createElement('p'); p.appendChild(this.input); body.appendChild(p); } form.appendChild(body); const footer = document.createElement('footer'); footer.classList.add(this.type, 'text'); const hiddenSubmitButton = document.createElement('button'); hiddenSubmitButton.value = 'submit'; hiddenSubmitButton.hidden = true; footer.appendChild(hiddenSubmitButton); const closeButton = document.createElement('button'); closeButton.classList.add(this.type, 'text', 'animated'); closeButton.innerText = this.footerText; footer.appendChild(closeButton); if (this.prompt === null) { closeButton.autofocus = true; } else { const submitButton = document.createElement('button'); submitButton.classList.add(this.type, 'background', 'animated'); submitButton.innerText = this.prompt; submitButton.value = 'submit'; footer.appendChild(submitButton); } form.appendChild(footer); this.dialog.addEventListener('close', (event) => { this.close(event.target.returnValue); }); this.dialog.appendChild(form); document.body.appendChild(this.dialog); } open() { this.dialog.showModal(); } close(returnValue) { if (this.prompt !== null) { if (returnValue === '') { this.responseValue = null; if (this.rejectPromise !== undefined) { this.rejectPromise('User canceled prompt'); } } else { this.responseValue = this.input.value; if (this.rejectPromise !== undefined) { this.resolvePromise(this.responseValue); } } } } response() { this.promise = new Promise((resolve, reject) => { if (this.responseValue !== undefined) { if (this.responseValue === null) { reject('User canceled prompt') } else { resolve(this.responseValue); } } else { this.resolvePromise = resolve; this.rejectPromise = reject; } }); return this.promise; } } main();
:root { --error: #c00; --error-dark: #900; --error-light: #f00; --info: #36c; --info-dark: #039; --info-light: #69f; --muted: #ddd; --muted-dark: #888; --muted-light: #eee; --success: #0c0; --success-dark: #090; --success-light: #0f0; --warning: #cc0; --warning-dark: #990; --warning-light: #ff0; } body { font-family: Arial, Helvetica, sans-serif; } button { border: 2px solid; border-radius: 10px; cursor: pointer; margin: 1em 0.5em; padding: 10px 15px; transition: transform 1s; } button:active { transform: scale(90%); } button.animated { background-color: transparent; overflow: hidden; position: relative; transition: color 0.3s, border-color 0.3s, transform 0.2s; z-index: 1; } button.animated:hover { border-color: transparent; } button.animated::after { border: 0; border-radius: 50%; content: ""; height: 200%; left: -50%; opacity: 0; position: absolute; transform: scale(0.1); transform-origin: center; transition: opacity 0.3s, transform 0.3s; top: -50%; width: 200%; z-index: -1; } button.animated:hover::after { opacity: 1; transform: scale(1); } input { border: 0; font: inherit; letter-spacing: normal; margin: 0; padding: 0; } input:focus, input:placeholder-shown { box-shadow: 0 2px 0 var(--muted); outline: none; } dialog { background-color: white; border: 0; border-radius: 10px; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); opacity: 0; outline: none; padding: 0; transform: scale(0); transition: all 0.4s allow-discrete; width: 50%; display: grid; grid-template-rows: auto 1fr; overflow: hidden; min-height:12em; } dialog:open { opacity: 1; transform: scale(1); } @starting-style { dialog:open { opacity: 0; transform: scale(0); } } dialog::backdrop { background-color: rgba(0, 0, 0, 0); transition: all 0.4s allow-discrete; } dialog:open::backdrop { background-color: rgba(0, 0, 0, 0.4); } @starting-style { dialog:open::backdrop { background-color: rgba(0, 0, 0, 0); } } dialog header, dialog main, dialog footer { display: flow-root; padding: 0 1em; text-align: center; } dialog header { background-color: black; color: white; } dialog main, dialog footer { background-color: white; color: black; } dialog form { display: grid; grid-template-rows: 1fr auto; overflow: hidden; } dialog header, dialog footer { flex: initial; } dialog main { overflow-y: auto; } .close { aspect-ratio: 1 / 1; background-color: rgba(0, 0, 0, 0); border: 0; border-radius: 50%; box-sizing: border-box; color: var(--muted); font-size: 1.2em; font-weight: bold; height: 1.2em; margin: 0; padding: 0; position: absolute; right: 0.5rem; top: 0.5rem; user-select: none; } .close:hover, .close:focus { background-color: rgba(255, 255, 255, 0.2); color: white; } .success.text, .info.text, .warning.text, .error.text, button.animated.success.background::after, button.animated.info.background::after, button.animated.warning.background::after, button.animated.error.background::after { background-color: white; } .success.background, .info.background, warning.background, error.background, button.animated.success.text:hover, button.animated.info.text:hover, button.animated.warning.text:hover, button.animated.error.text:hover { color: white; } button.animated.success.text, button.animated.info.text, button.animated.warning.text, button.animated.error.text { border-color: var(--muted); } .success.text, button.animated.success.background:hover { color: var(--success); } .success.background, button.animated.success.text::after { background-color: var(--success); } button.animated.success.text:hover, button.animated.success.background { border-color: var(--success); } .info.text, button.animated.info.background:hover { color: var(--info); } .info.background, button.animated.info.text::after { background-color: var(--info); } button.animated.info.text:hover, button.animated.info.background { border-color: var(--info); } .warning.text, button.animated.warning.background:hover { color: var(--warning); } .warning.background, button.animated.warning.text::after { background-color: var(--warning); } button.animated.warning.text:hover, button.animated.warning.background { border-color: var(--warning); } .error.text, button.animated.error.background:hover { color: var(--error); } .error.background, button.animated.error.text::after { background-color: var(--error); }

Related Articles