Complex layout using React and CSS Grid - css

So I'm attempting to create the above. Is there a smart way of making the menu component? Or does the container element have to cover most of the content component (it has to be a rectangle and in itself use CSS Grid to position the left part and the top part of the menu)?

This doesn't exactly match your single 'L' shape component requirement, but should get you closer than you were before.
A couple notes worth mentioning:
This simply answers your question as a html/css question, not in React style. You could split this up into two components like you were hoping for by using every html/css element other than body-content, then having body-content html/css as the child
Not sure exactly how you want to handle your content, but with this code the App-Header will scroll with your content. If you want it to be fixed and stay above the content copy the MainMenu's css, but style it for vertical scrolling.
Hope this gets you going in the right direction.
body {
margin: 0px;
}
.App-header {
background-color: #203764;
height: 80px;
padding: 10px;
color: white;
}
/* Style page content */
.main-content {
margin-left: 160px; /* Same as the width of the MainMenu */
}
.body-content {
padding: 20px;
}
/* The MainMenu menu */
.MainMenu {
height: 100%; /* Full-height: remove this if you want "auto" height */
width: 160px; /* Set the width of the sidebar */
position: fixed; /* Fixed Sidebar (stay in place on scroll) */
z-index: 1; /* Stay on top */
top: 0; /* Stay at the top */
left: 0;
background-color: #111; /* Black */
overflow-x: hidden; /* Disable horizontal scroll */
color: #FFF;
}
<div class="App">
<div class="MainMenu">Main Menu</div>
<div class="main-content">
<header class="App-header">Header</header>
<div class="body-content">Content</div>
</div>
</div>

Related

Place div between divs in mobile in plain css

I trying to place a div between divs for a mobile screen.
I don't want to use javascript, just plain css. Is there a way to achieve it?
I'm experimenting with flexboxes order but can't reach my goal.
.parent {
display: flex;
justify-content: flex-start;
}
.left {
background-color: yellow;
padding: 20px;
width: 50%;
}
.left-1 {
background-color: greenyellow;
padding: 20px;
}
.left-3 {
background-color: gray;
padding: 20px;
}
.right {
background-color: cyan;
padding: 20px;
width: 50%;
}
<section class="parent">
<div class="left">
<div class="left-1">1</div>
<div class="left-3">3</div>
</div>
<div class="right">2</div>
</section>
The easiest way to achieve your desired outcome is to use CSS grid layout, which allows for all elements to be siblings, along with a media-query:
/* simple reset to ensure all element sizes are calculated the same way,
and with the same base-styles: */
*,
::before,
::after {
box-sizing: border-box;
font-size: 16px;
font-family: system-ui, sans-serif;
font-weight: 400;
margin: 0;
padding: 0;
}
.parent {
/* using CSS Grid for layout: */
display: grid;
/* setting a gap between adjacent-elements,
(shorthand for 'row-gap' and 'column-gap') */
gap: 0.5em;
/* defining named areas for the contents to be positioned,
based on rows; the first row comprises of one area named:
'leftTop' and the second named 'main'; the second row
has 'leftLower' and 'main'; the reason that 'main' appears
twice is that we want the element in that position to span
across both rows: */
grid-template-areas:
"leftTop main"
"leftLower main";
/* setting height and width to be full-screen: */
width: 100vw;
height: 100vh;
/* setting padding, so that there is a visible gap between the
elements and the page's borders (obviously, adjust to taste): */
padding: 0.5em;
}
/* writing the common styles shared by all child-elements into the same
place for ease of maintenance/updates: */
.parent div {
padding: 20px;
}
/* the left-1 and left-2 elements will be laid out automatically according
to their order in the DOM, once any grid-items (the 'left-1', 'left-2',
and 'right' elements) have been allocated their specific places according
to the author's design: */
.left-1 {
background-color: greenyellow;
}
.left-3 {
background-color: gray;
}
.right {
background-color: cyan;
/* here we explicitly place this element into the named (but not quoted)
main grid-area: */
grid-area: main;
}
/* when the screen falls below 450px in width (obviously adapt to your own
requirements): */
#media screen and (max-width: 450px) {
/* the grid-template-areas are redefined into three single-column rows: */
.parent {
grid-template-areas: "topLeft" "main" "lowerLeft";
}
}
<section class="parent">
<!-- removed the wrapper 'left' column element, in order to allow the
'right' element to be positioned between the 'left-1' and 'left-3'
elements when the screen-size changes: -->
<div class="left-1">1</div>
<div class="left-3">3</div>
<div class="right">2</div>
</section>
JS Fiddle demo.
References:
box-sizing.
display.
font-family.
font-size.
font-weight.
gap.
grid-template-areas.
margin.
#media queries.
padding.
Bibliography:
"A Complete Guide to Grid."
"Basic Concepts of grid layout."
"CSS Grid Layout."

How can I hide the vertical scrollbar, while still showing my horizontal, and keep scroll functionality on both?

I want to hide my vertical scrollbar, but still be able to scroll both vertically and horizontally.
I have tried using
overflow-y: hidden; overflow-x: scroll;
But it removes the ability to scroll vertically.
I have tried styling the scrollbar with
html .example-container {
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none; /* IE 10+ */
}
and
html .example-container::-webkit-scrollbar { /* WebKit */
width: 4;
height: 0;
}
It makes both scrollbars hidden, and it is important for the horizontal scrollbar to be visible.
Example of all three methods tried:
https://stackblitz.com/edit/angular-gyq9ub
If you stylize your horizontal scrollbar then your vertical scrollbar somehow disappears and you are still able to scroll vertically as you asked. But it's unclear to me why it works
.example-container::-webkit-scrollbar {
width: 6px;
height: 6px;
}
.example-container::-webkit-scrollbar-thumb:horizontal {
background: #a1a1a1;
border-radius: 3px;
background-clip: padding-box;
}
/* Track */
.example-container::-webkit-scrollbar-track:horizontal {
background-color: #dbdbdb;
border-radius: 3px;
background-clip: padding-box;
}
Create a wrapper div for your inner div and then set inner div overflow = auto. And the outer div overflow to hidden.
For example;
<div class="wrapper-div">
<div class="example-container">
<p class="content">
Start editing to see some magic happen :)
</p>
---
</div>
</div>
CSS:
.example-container {
height: 100px;
overflow: auto;
max-height: 100%;
margin-right: -100px;
padding-right: 100px;
}
.wrapper-div {
overflow: hidden;
}
Thats it! Please check this answer for better understanding.

Make content DIV overlap header and footer

I'm having some issues with creating this effect with CSS:
http://i.stack.imgur.com/sMBmg.jpg
Basically, I want my content div to float on top and slightly overlap both the header and the footer elements. I've played around with some absolute positioning but I'm not sure if that's the best way to go. I want a responsive solution that works for all devices and screen sizes. Any suggestions?
Here is one way you could do it.
If this is your HTML:
<div class="header">Header</div>
<div class="content">Content</div>
<div class="footer">Footer</div>
Apply the following CSS:
.header, .footer {
height: 100px; /* not strictly needed... */
border: 1px solid blue;
}
.content {
width: 50%; /* for example... */
height: 400px;
background-color: yellow;
margin: 0 auto;
border: 1px dotted blue;
}
.header {
margin-bottom: -25px;
}
.footer {
margin-top: -25px;
}
.content {
position: relative;
z-index: 1;
}
You can see the demo at: http://jsfiddle.net/audetwebdesign/CNnay/
You set up three block level elements for the header, content and footer.
Apply negative margins to the bottom of the header and the top of the footer to
create the offset effect.
Finally, apply z-index to .content to tweak the stacking order so that the
content block is painted over the footer block.
In this layout, the content block will expand vertically as you add more content.
The results looks like:
You can try position:fixed or z-index:2000 of your div class
i have created this http://jsfiddle.net/RVnU7/1/

CSS/HTML: Child DIV overflows parent

How can I make the parent DIV wrap around the child DIVs? The problem lies with position:absolute in .nav-content.
http://jsfiddle.net/9H77Y/8/
EDIT: Well, apparently what I want is impossible. The only way to work around this would be javascript which would defeat the purpose of this in the first place. However, setting a fixed height to nav-tabs will work.
HTML
<div class="nav-tabs-wrapper">
<div class="nav-tabs">
<div class="nav-tab">
<input type="radio" id="tab1" name="nav-group" checked>
<label for="tab1">foooooooo</label>
<div class="nav-content">
<div> stuff1 </div>
</div>
</div>
<div class="nav-tab">
<input type="radio" id="tab2" name="nav-group">
<label for="tab2">bar</label>
<div class="nav-content">
<div> stuff2 </div>
</div>
</div>
</div>
</div>
CSS
.nav-tabs-wrapper
{
padding: 10px; /* separates the code from other content */
border: 1px solid #F00; /* visibility aid */
}
.nav-tabs
{
position: relative; /* needed as future positioning reference base */
clear: both;
height: 200px; /* Unfortunate */
padding-left: 10px; /* provides the paragraph-tab effect to the tabs */
font: 100%/1.4 Verdana, Arial, Helvetica, sans-serif;
}
.nav-tab
{
float: left; /* keeps the tabs inline with no gap [inline-block introduces gaps] */
}
.nav-tab label
{
display: block; /* needed so tabs can be positioned correctly to hide nav-content border */
position: relative; /* needed to position tabs correctly */
top: 1px; /* lowers the tabs to cover the border of nav-content; needed so bottom corners aren't slanted, but a 90deg angle */
padding: 4px;
border: 1px solid #999;
border-bottom-width: 0px; /* removes bottom border; needed so bottom corners aren't slanted, but a 90deg angle */
background-color: #CCC;
}
.nav-tab [type=radio]
{
display: none; /* hide the radio selectors */
}
.nav-tab [type=radio]:checked ~ label
{
z-index: 2; /* makes sure that the active tab is drawn above nav-content to cover border */
background-color: #FFF; /* covers the nav-content border */
}
.nav-tab [type=radio]:checked ~ .nav-content
{
visibility: visible !important; /* unhides the nav-content div for the current tab */
}
.nav-tab:nth-child(n+2)
{
margin-left: -1px; /* positions the left border of every second+ tab over the previous tab's right border */
}
.nav-content
{
visibility: hidden; /* hides the content by default */
position: absolute; /* positions the content for all tabs to the absolute left relative to the tabs */
left: 0; /* undo's the padding from the paragraph-tab effect */
width: 100%; /* fills the nav-content DIV completely for a better looking border */
z-index: 1; /* makes sure that the border is drawn under the tabs */
border: 1px solid #999;
}
.nav-content div
{
padding: 10px; /* separate div needed to keep nav-content from overflowing due to padding */
}
You can't account for position:absolute elements.
They are completely removed from the flow of the document.
Quoting the Specs
absolute
The box's position (and possibly size) is specified with the 'top', 'right', 'bottom', and 'left' properties. These properties specify offsets with respect to the box's containing block. Absolutely positioned boxes are taken out of the normal flow. This means they have no impact on the layout of later siblings. Also, though absolutely positioned boxes have margins, they do not collapse with any other margins.
Give a definite height to .nav-tab and give overflow:auto (or overflow:hidden) to .nav-tabs-wrapper

Overflow-x: hidden also hides vertical content too

I have a DIV measuring 400px wide, containing two DIVs side-by-side, each with width of 400px and height of 600px. The width of both DIVs is fixed, however the height can vary. I'd like to hide the second DIV and show the first completely, with no scrolling inside the DIV.
My solution, I thought, was to hide the overflow-x. This seems to also hide the y overflow too.
Here's my code:
#schools-sub-nav {
}
#schools-container {
width: 400px; /* Set the width of the visible portion of content here */
background-color: fuchsia;
position: relative;
overflow-x: hidden;
}
#schools-list {
width: 400px; /* Set the width of the visible portion of content here */
height: 600px; /* Delete the height, let the content define the height */
background-color: purple;
position: absolute;
top: 0;
left: 0;
}
#boards-list {
width: 400px; /* Set the width of the visible portion of content here */
height: 600px; /* Delete the height, let the content define the height */
background-color: green;
position: absolute;
top: 0;
left: 400px;
}
<div id="schools-sub-nav"> Schools List // Boards List </div>
<div id="schools-container">
<div id="schools-list"> One </div>
<div id="boards-list"> Two </div>
</div>
I expect #schools-list to be visible, but for some reason overflow-x: hidden in #schools-container hides it.
The way you made the two divs (with an absolute position) void the overflow rule!
You need to change the position type (to normal/not absolute) and I suggest using floats, finally, the container div that you want to apply the overflow, needs to have a way to fit it, like placing a div at the end with clear: both (in the case of using floats).
EDIT: I just tried it and you can hide the second div by following the upper suggestion and adding another surrounding div inside with a very large width and change the overflow-x to overflow for the main container div.
Like this:
<div id="schools-container">
<div id="schools-container-inside">
<div id="schools-list"> One </div>
<div id="boards-list"> Two </div>
</div>
</div>
And then the CSS (I commented the original not used CSS and added the new div class at the end):
#schools-container {
width: 400px; /* Set the width of the visible portion of content here */
background-color: fuchsia;
position: relative;
/*overflow-x: hidden;*/
overflow: hidden;
}
#schools-list {
width: 400px; /* Set the width of the visible portion of content here */
height: 600px; /* Delete the height, let the content define the height */
background-color: purple;
/*
position: absolute;
top: 0;
left: 0;
*/
float: left;
}
#boards-list {
width: 400px; /* Set the width of the visible portion of content here */
height: 600px; /* Delete the height, let the content define the height */
background-color: green;
/*
position: absolute;
top: 0;
left: 400px;
*/
float: left;
}
#schools-container-inside {
width: 10000px;
overflow: hidden;
}
JsFiddle here: http://jsfiddle.net/MbMAc/
I think you need this
#schools-container {
width: 400px; /* Set the width of the visible portion of content here */
background-color: fuchsia;
position: relative;
overflow-x: hidden;
overflow-y:auto;
height:600px;
}
You need to define height of main div as well.

Resources