I want this only with CSS-GRID
I want to fit the main element to full width if aside is not present.
html,
body {
height: 100%;
margin: 0;
padding: 0;
font-size: 2rem;
}
div.root {
height: 100%;
background-color: blueviolet;
display: grid;
grid-template-columns: 200px auto;
}
aside {
background-color: aquamarine;
}
main {
background-color: burlywood;
}
<div class="root">
<aside> aside </aside>
<main> main </main>
</div>
I've search on the SOF and found the following but It didn't work STACKOVERFLOW
What I've trid is to give the grid-template-columns as auto auto and add the width to the aside but then main doesn't stretch to its full width.
html,
body {
height: 100%;
margin: 0;
padding: 0;
font-size: 2rem;
}
div.root {
height: 100%;
background-color: blueviolet;
display: grid;
grid-template-columns: auto auto;
}
aside {
width: 200px;
background-color: aquamarine;
}
main {
background-color: burlywood;
}
<div class="root">
<!-- <aside> aside </aside> -->
<main> main </main>
</div>
You could use the + selector in CSS, though this only works if your aside is on the left.
html,
body {
height: 100%;
margin: 0;
padding: 0;
font-size: 2rem;
}
div.root {
height: 100%;
background-color: blueviolet;
display: grid;
grid-template-columns: 200px auto;
}
aside {
background-color: aquamarine;
grid-column-start: span 1;
}
main {
background-color: burlywood;
grid-column-start: span 2;
}
aside + main {
grid-column-start: span 1;
}
<div class="root">
<!--<aside> aside </aside>-->
<main> main </main>
</div>
<br/><br/>
<div class="root">
<aside> aside </aside>
<main> main </main>
</div>
Use display:flex;
html,
body {
height: 100%;
margin: 0;
padding: 0;
font-size: 2rem;
}
div.root {
height: 100%;
background-color: blueviolet;
display:flex;
}
aside {
background-color: aquamarine;
min-width:200px;
max-width:200px;
}
main {
background-color: burlywood;
flex:1;
}
<div class="root">
<!-- <aside> aside </aside> -->
<main> main </main>
</div>
Related
I have a simple menu and content div structure. The menu has no fixed size and can expand depending on its content. The content div underneath should take the available space and scroll its own content if overflowing. Unfortunately, flexbox now behaves in such a way that the content div, due to its flex:1 property, expands according to its content instead of scrolling the content.
Is there a way to preserve the dynamic sizes using flex:1 and also have the content of the content div scroll?
function toggleMenu() {
const menu = document.querySelector(".menu");
if(menu.classList.contains("open")) {
menu.querySelector(".text").innerHTML = "<p> small text </p>";
menu.classList.remove("open");
}else {
menu.querySelector(".text").innerHTML = "<h1> im the menu </h1>";
menu.classList.add("open");
}
}
body {
padding: 0;
margin: 0;
background-color: #17141d;
display: flex;
height: 100vh;
}
.main {
display: flex;
flex-direction: column;
flex: 1;
background-color: grey;
}
.menu {
background-color: blueviolet;
}
.content {
display: flex;
flex: 1;
background-color: aqua;
}
.segment-wrapper {
flex: 1;
display: flex;
background-color: red;
flex-direction: column;
overflow-y: scroll;
padding: 10px;
box-sizing: border-box;
}
.segment {
height: 500px;
background-color: green;
border-radius: 5px;
border: solid 1px black;
width: 100%;
margin-bottom: 10px;
}
<div class="main">
<div class="menu open">
<div class="text"><h1>im the menu</h1></div>
<button onclick="toggleMenu()">Toggle</button>
</div>
<div class="content">
<div class="segment-wrapper">
<div class="segment">
</div>
<div class="segment">
</div>
<div class="segment">
</div>
</div>
</div>
</div>
you are missing
an height on .main to size it according to body or the viewport's height.
overflow on .content, so it overflows, unless you want .main to overflow (which body does already)
and finally flex-shrink:0; on .segment so it doesn't shrink :)
here an example of what i understood you were after:
function toggleMenu() {
const menu = document.querySelector(".menu");
if(menu.classList.contains("open")) {
menu.querySelector(".text").innerHTML = "<p> small text </p>";
menu.classList.remove("open");
}else {
menu.querySelector(".text").innerHTML = "<h1> im the menu </h1>";
menu.classList.add("open");
}
}
body {
padding: 0;
margin: 0;
background-color: #17141d;
display: flex;
height: 100vh;
}
.main {
display: flex;
flex-direction: column;
flex: 1;
background-color: grey;
max-height;100%;
}
.menu {
background-color: blueviolet;
}
.content {
display: flex;
flex: 1;
background-color: aqua;
overflow:auto;
}
.segment-wrapper {
flex: 1;
display: flex;
background-color: red;
flex-direction: column;
overflow-y: scroll;
padding: 10px;
box-sizing: border-box;
}
.segment {
flex-shrink:0;
height: 500px;
background-color: green;
border-radius: 5px;
border: solid 1px black;
width: 100%;
margin-bottom: 10px;
}
<div class="main">
<div class="menu open">
<div class="text"><h1>im the menu</h1></div>
<button onclick="toggleMenu()">Toggle</button>
</div>
<div class="content">
<div class="segment-wrapper">
<div class="segment">
</div>
<div class="segment">
</div>
<div class="segment">
</div>
</div>
</div>
</div>
I'm creating simple page with a <header> and a <section>. In the section I have 3 divs and I am positioning them with display: flex; and justify-content: space-between.
The problem is that I also use JS slideToggle() on two of them (extreme ones). It is changing the layout of my center div after they are going up. How can I do it so that my center div doesn't change position after one of the others is slid up?
$(document).ready(function() {
$('#playlist').click(function() {
$('#nav').slideToggle();
});
});
$(document).ready(function() {
$('#songs').click(function() {
$('#listSongs').slideToggle();
});
});
section {
display: flex;
justify-content: space-between;
}
#listSongs {
margin-top: 50px;
height: 550px;
background-color: black;
border-radius: 5px;
font-size: 25px;
width: 200px;
}
#listSongs p {
margin-top: 5px;
width: 200px;
text-align: center;
overflow: hidden;
height: 35px;
line-height: 50px;
color: white;
}
#player {
color: red;
}
#nav {
margin-top: 50px;
height: 550px;
background-color: black;
border-radius: 20px;
width: 200px;
}
.hidden {
margin-top: 50px;
height: 550px;
background-color: black;
border-radius: 20px;
width: 200px;
visibility: hidden;
}
#nav p {
text-align: center;
}
#nav ul {
list-style-type: none;
text-align: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section>
<div id="listSongs">
<p>Authors:</p>
<div class="after"></div>
</div>
<div id="player">
<p>something</p>
</div>
<div id="nav">
<p>something</p>
</div>
</section>
The issue is because when the slideUp/slideDown/slideToggle methods complete, they set display: none on the target element. This is what causes the layout of your page to shift.
To workaround, and improve the animation, you can use CSS instead. Use the transition property to animate the height setting. Then you can toggle a class which sets height: 0 on the target element. Try this:
$(document).ready(function() {
$('#playlist').click(function() {
$('#nav').toggleClass('hide');
});
$('#songs').click(function() {
$('#listSongs').toggleClass('hide');
});
});
body { background-color: #CCC; }
section {
display: flex;
justify-content: space-between;
}
section > div.panel {
margin-top: 50px;
height: 550px;
background-color: black;
border-radius: 5px;
font-size: 25px;
width: 200px;
transition: height 0.4s;
overflow: hidden;
}
section > div.panel.hide {
height: 0;
}
section > div.panel p {
margin-top: 5px;
width: 200px;
text-align: center;
overflow: hidden;
height: 35px;
line-height: 50px;
color: white;
}
#player {
color: red;
}
#nav {
border-radius: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="playlist">Playlist</button>
<button id="songs">Songs</button>
<section>
<div id="listSongs" class="panel">
<p>Authors:</p>
<p>lorem ipsum</p>
<div class="after"></div>
</div>
<div id="player">
<p>something</p>
</div>
<div id="nav" class="panel">
<p>something</p>
</div>
</section>
Note that I also rearranged some of the CSS to make it more generic with less repetition.
I have a nested child container and when I'm trying to scrollIntoView it breaks the parent container. I'm not able to understand why it's acting like this. Please help me out in this.
Please have a look at the code below or on jsfiddle
function moveToTop() {
console.log('MOVE TO TOP::');
const child = document.getElementById('child');
child.scrollIntoView({
behavior: "smooth"
});
}
#parent {
background-color: blue;
padding: 10px;
height: 500px;
overflow: hidden;
display: flex;
flex-direction: column;
}
#scroller {
overflow: auto;
padding: 10px;
background-color: red;
flex-grow: 1;
}
#child {
height: 10000px;
background-color: green;
}
body {
overflow: hidden;
color: #fff;
font-weight: bold;
}
button {
position: fixed;
bottom: 20px;
width: 140px;
left: 20%;
right: 0;
}
<div id="parent">
PARENT
<div id="something">Something</div>
<div id="scroller">
CHILD
<div id="child">
GRAND CHILD
<button onclick="moveToTop()">Top</button>
</div>
</div>
</div>
The whole problem is that scrollIntoView() is moving the window. But since the #parent overflow is hidden, when the window is moved, this element itself breaks. I could suggest setting a position: fixed for the #parent, which will solve your problem, but it can harm the layout in general.
Use the scroll() method. The scrolling mechanism itself is:
scroller.scroll(0, child.offsetTop - 55);
child.offsetTop - top element;
55 - distance from the top of the #parent to the top #scroller.
The transition animation must be set to css, in selector #scroller. Like that:
#scroller {
...
scroll-behavior: smooth;
}
function moveToTop() {
console.log('MOVE TO TOP::');
const child = document.getElementById('child');
const scroller = document.getElementById('scroller');
scroller.scroll(0, child.offsetTop - 55);
}
#parent {
background-color: blue;
padding: 10px;
height: 500px;
overflow: hidden;
display: flex;
flex-direction: column;
}
#scroller {
overflow: auto;
padding: 10px;
background-color: red;
flex-grow: 1;
scroll-behavior: smooth;
}
#child {
height: 10000px;
background-color: green;
}
body {
overflow: hidden;
color: #fff;
font-weight: bold;
}
button {
position: fixed;
bottom: 20px;
width: 140px;
left: 20%;
right: 0;
}
<div id="parent">
PARENT
<div id="something">Something</div>
<div id="scroller">
CHILD
<div id="child">
GRAND CHILD
<button onclick="moveToTop()">Top</button>
</div>
</div>
</div>
I am building a mobile application which will have a scrollable element in the middle of the screen. Currently when I try and scroll the entire app moves. I would like the all other elements to remain fixed while my element scrolls.
Here is my main React App:
class MobileServices extends Component {
render() {
return (
<div className={style.app}>
<div className={style.mobileHeader}>
<div className={style.logoBox}>
Logo Here
</div>
<div className={style.contactBox}>
</div>
</div>
<div className={style.mainContent}>
<div className={style.contentOne}></div>
<div className={style.contentTwo}></div>
<div className={style.contentThree}></div>
</div>
</div>
);
}
}
Here is the CSS:
html, body {
margin: 0;
/* height: 100% */
}
.app {
background-color: green;
background-size : cover;
background-attachment: fixed;
height: 100vh;
width: 100vw;
overflow: hidden;
}
.contactBox {
margin: 1rem;
padding: 1rem;
}
.contentOne {
background-color: blue;
display: flex;
height: 10rem;
width: 100vw
}
.contentTwo {
background-color: red;
display: flex;
height: 10rem;
width: 100vw
}
.logoBox {
border: 2px solid white;
margin: 1rem;
padding: 2rem;
}
.mainContent {
flex: 1;
display: flex;
overflow: scroll;
margin-top: 4rem;
height: 10rem;
width: 300vw;
overflow-x: auto;
}
.mobileHeader {
display: flex;
justify-content: space-between;
width: 100%;
}
I have tried making the app class fixed, but that only prevented me from being able to scroll at all.
body, html {
width: 100%;
height: 100%;
overflow: hidden;
}
.app {
// your css and
display: flex;
flex-direction: column;
}
.mainContent {
flex-grow: 1;
overflow: auto;
// rest of your css
}
Optional, you can set your mobielHeader to have position: sticky
I have the next page:
<div id = "menu">
Menu on the left side
</div>
<div id = "header">
Header content of the page
</div>
<div id = "body">
Data Data Data Data Data Data Data
</div>
<div id = "footer">
Additional Information
</div>
Whith Next layout: Menu should be on the left side:
#menu{
background: #244a7c;
padding: 7px 23px 0 7px;
width: 299px;
height: 1000px;
overflow: inherit;
margin-left: 0px;
display: block;
float: left;
}
#header{
display: inline-block;
width: 400px;
border-bottom: 1px solid rgb(238, 238, 238);
}
Body can have different data inside. My problem is:
When content of the body more than user page I want to fix all div except body. Menu should be on the left side, Header should be on the top of the page and footer on the bottom and ONLY body should be scrollable.
Any help, please.
Thanks!
Here's 2 Pure CSS solution
Without fixing any height (header/footer) or width (left column).
I actually prefer the second solution. (even tho he has less browser support)
1 - using CSS tricks
this is a totally responsive design and work well with all browsers (IE10, FF, Chrome, Safari, Opera, mobile browsers)
Working Fiddle
HTML:
<div class="Container">
<div class="Header">
</div>
<div class="HeightTaker">
<div class="Wrapper Container Inverse">
<div>
<div class="Footer">
</div>
</div>
<div class="HeightTaker">
<div class="Wrapper">
<div class="LeftMenu">
</div>
<div class="Content">
</div>
</div>
</div>
</div>
</div>
</div>
CSS:
*
{
margin: 0;
padding: 0;
}
html, body, .Container
{
height: 100%;
}
.Container:before
{
content: '';
height: 100%;
float: left;
}
.HeightTaker
{
position: relative;
z-index: 1;
}
.HeightTaker:after
{
content: '';
clear: both;
display: block;
}
.Wrapper
{
position: absolute;
width: 100%;
height: 100%;
}
.Inverse, .Inverse > *
{
-moz-transform: rotateX(180deg);
-ms-transform: rotateX(180deg);
-o-transform: rotate(180deg);
-webkit-transform: rotateX(180deg);
transform: rotateX(180deg);
}
.LeftMenu
{
height: 100%;
float: left;
}
.Content
{
overflow: auto;
height: 100%;
}
/*For demonstration only*/
p
{
font-size: 1.3em;
}
.Important
{
font-weight: bolder;
color: white;
}
body > .Container
{
text-align: center;
}
.Header
{
background-color: #bf5b5b;
}
.LeftMenu
{
background-color: #bdbe4c;
}
.Content
{
background-color: #90adc1;
}
.Footer
{
background-color: #b5a8b7;
}
2 - using Flex
This layout can also be achieved using flex, but the current browser support is pure.
Here's a Working Fiddle only FF,Chrome,IE10.
HTML: (simpler)
<header>
</header>
<section class="Middle">
<div class="LeftMenu">
</div>
<div class="Content">
</div>
</section>
<footer>
</footer>
CSS:
*
{
margin: 0;
padding: 0;
}
html, body
{
height: 100%;
text-align: center;
}
body
{
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
.Middle
{
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 0;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
overflow: hidden;
}
.Content
{
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 0 0;
overflow: auto;
}
/*For demonstration only*/
p
{
font-size: 1.3em;
}
.Important
{
font-weight: bolder;
color: white;
}
header
{
background-color: #bf5b5b;
}
.LeftMenu
{
background-color: #bdbe4c;
}
.Content
{
background-color: #90adc1;
}
footer
{
background-color: #b5a8b7;
}
If you set the header, footer & menu position as fixed & leave the body as it is, it should work. Only the body will be scrollable.
#header {
position: fixed;
top: 0;
display: inline-block;
width: 400px;
border-bottom: 1px solid rgb(238, 238, 238);
}
#footer {
position: fixed;
bottom: 0;
}
#menu {
position: fixed;
left: 0;
background: #244a7c;
padding: 7px 23px 0 7px;
width: 299px;
height: 1000px;
}
#body {
margin-left: 300px;
margin-top: <header-height>;
margin-bottom: <footer-height>;
}