CSS layout 3 toggleable columns 1 toggleable terminal-like footer - css

Is there a cleaner/shorter way to achieve the same result with cross-browser CSS and using javascript only to toggle classes?
I'm trying to create a layout like the above but I've never tried to set everything absolutely as I did here so I don't know what might be the disadvantage.
$(".left-col-content > .content").append(() => {
return "left-col<br>".repeat(350);
});
$(".right-col-content > .content").append(() => {
return "right-col<br>".repeat(350);
});
$(".terminal-row > .content").append(() => {
return "terminal<br>".repeat(350);
});
$(".body-col-content > .content").append(() => {
return "content<br>".repeat(350);
});
$(".body-col-header > .content").append(() => {
left_btn = $("<button>Toggle Left</button>").click(() => {
$(".left-col").toggle();
$(".body-col").toggleClass("left-hidden");
});
right_btn = $("<button>Toggle Right</button>").click(() => {
$(".right-col").toggle();
$(".body-col").toggleClass("right-hidden");
});
terminal_btn = $("<button>Toggle Terminal</button>").click(() => {
$(".terminal-row").toggle();
$(".main-row").toggleClass("terminal-hidden");
});
buttons = $("<div></div>")
.append(left_btn)
.append(right_btn)
.append(terminal_btn);
return buttons;
});
.container {
height: 100%;
}
.container .main-row {
height: inherit;
position: absolute;
top: 0px;
right: 0px;
bottom: 50px;
left: 0px;
}
.container .main-row.terminal-hidden {
bottom: 0px;
}
.container .main-row .left-col {
width: 150px;
left: 0px;
top: 0px;
bottom: inherit;
position: absolute;
background-color: yellow;
}
.container .main-row .left-col .left-col-header {
height: 50px;
width: inherit;
position: inherit;
background-color: orange;
}
.container .main-row .left-col .left-col-content {
width: inherit;
top: 50px;
bottom: 0px;
position: inherit;
overflow-y: scroll;
}
.container .main-row .left-col .left-col-content .content {
padding: 15px;
}
.container .main-row .right-col {
width: 150px;
right: 0px;
top: 0px;
bottom: inherit;
position: absolute;
background-color: yellow;
}
.container .main-row .right-col .right-col-header {
height: 50px;
width: inherit;
position: inherit;
background-color: orange;
}
.container .main-row .right-col .right-col-content {
width: inherit;
top: 50px;
bottom: 0px;
position: inherit;
overflow-y: scroll;
}
.container .main-row .right-col .right-col-content .content {
padding: 15px;
}
.container .main-row .body-col {
right: 150px;
left: 150px;
top: 0px;
bottom: inherit;
position: absolute;
background-color: green;
}
.container .main-row .body-col.right-hidden {
right: 0px;
}
.container .main-row .body-col.left-hidden {
left: 0px;
}
.container .main-row .body-col .body-col-content {
width: 100%;
top: 50px;
bottom: 0px;
position: inherit;
overflow-y: scroll;
}
.container .main-row .body-col .body-col-content .content {
padding: 25px;
}
.container .main-row .body-col .body-col-header {
height: 50px;
width: 100%;
position: inherit;
background-color: red;
}
.container .terminal-row {
height: 50px;
width: 100%;
bottom: 0px;
right: 0px;
position: absolute;
background-color: black;
color: green;
overflow-y: scroll;
}
.container .terminal-row .content {
padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class="container">
<div class="main-row">
<div class="left-col">
<div class="left-col-header">
<div class="content">
</div>
</div>
<div class="left-col-content">
<div class="content">
</div>
</div>
</div>
<div class="right-col">
<div class="right-col-header">
<div class="content">
</div>
</div>
<div class="right-col-content">
<div class="content">
</div>
</div>
</div>
<div class="body-col">
<div class="body-col-header">
<div class="content">
</div>
</div>
<div class="body-col-content">
<div class="content">
</div>
</div>
</div>
</div>
<div class="terminal-row">
<div class="content">
</div>
</div>
</div>

This is not fully finished yet, but will give you a frame you can use to work with.
As you can see in the snippet, I have used very rarely used properties of the <style> tag namely id and in javascript .disabled.
As style tags use and comply to W3 'Global HTML Attributes' rules w3schools.com: HTML style tag you can simply give them an #id and toggle them en/disabled with a simple line of javascript.
As you can see in the Snippet I have defined all major elements as Flexbox Containers with some very generic top/bottom/center/middle classes to get the structure you want/need, leaving you with all the room you might need to specific stuff like spacing, fontsizing create you own #id's, etc.
Comment back when you need more info. (don't forget to close the question if you did get the answer you needed.)
In the code you can see that I first disabled the columns and drawer with display: none, each in its own style block.
Then I define them visible with display: flex (as they are flexbox div's) and enable/disable that style block on request by toggling it enabled/disabled with simple javascript.
function toggleStyle(id) { var el = document.getElementById(id); el.disabled = !el.disabled }
<style>
body { margin: 0 }
header,footer,main,section,item,
div { display: flex }
header,footer,section,div { flex-direction: row }
main,item { flex-direction: column }
header,footer,item,div { flex-wrap: wrap }
header { min-height: 3.5rem } /* 3.5 * 16px */
footer { min-height: 2.5rem }
main { height: 100vh; justify-content: space-between }
section { height: 100%; justify-content: space-between }
.drawer { align-content: space-between }
.left,.right { width: 12.5% }
.center { flex: 1 }
.middle { flex: 1; width: 100% }
.top,.bottom { height: 2rem; width: 100% }
.center-col { flex: 1 }
* { outline: 1px dashed }
</style>
<style>.drawer.left { display: none }</style>
<style>.drawer.bottom { display: none }</style>
<style>.drawer.right { display: none }</style>
<style id="stl-left-col" >.drawer.left { display: flex }</style>
<style id="stl-terminal" >.drawer.bottom { display: flex }</style>
<style id="stl-right-col">.drawer.right { display: flex }</style>
<body>
<main>
<header>
<input type="button" onclick="toggleStyle('stl-left-col')" value="left column">
<input type="button" onclick="toggleStyle('stl-terminal')" value="terminal row">
<input type="button" onclick="toggleStyle('stl-right-col')" value="right column">
</header>
<section class="content">
<item class="drawer left">
<div class="top" >left top </div>
<div class="middle">left middle</div>
<div class="bottom">left bottom</div>
</item>
<item class="content center">
<div class="top">main top</div>
<div class="middle">main middle
</div>
<div class="bottom">main bottom</div>
</item>
<item class="drawer right">
<div class="top" >right top </div>
<div class="middle">right middle</div>
<div class="bottom">right bottom</div>
</item>
</section>
<footer class="drawer bottom">some footer</footer>
</main>
</body>

Related

How to render subchild above parent overlay

I want a gray overlay above all children except for the selected one. Given the following structure:
<div class="parent">
<!-- I have this subparent which is absolute. I cannot remove it... -->
<div class="subParent1">
<div class="subParent2">
<!-- This child I want to be above the OVERLAY, aka not greyed out -->
<div class="child selected">child</div>
<div class="child">child</div>
<div class="child">child</div>
</div>
</div>
<!-- This component is underneat subParent in the tree structure -->
<div class="grayOverlay"></div>
</div>
Here's an exact fiddle. Maybe, I could use a pseudo-element instead?
PS: I updated the children to be a bit more nested to align with my actual code.
You can take the reference from below code. I have altered the CSS a bit. I have added z-index wherever required you can optimise that. Also, removed position: absolute; from subParent1 and added top: 0; left: 0; on the grayOverlay. You can optimise it or change it as per you preference.
.parent {
width: 300px;
height: 300px;
position: relative;
background-color: gray;
}
.grayOverlay {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-color: rgb(107 114 128 / 0.8);
z-index: 11000;
}
.subParent1 {
display: flex;
flex-direction: column;
width: 100%;
z-index: 12000;
}
.child {
color: black;
width: 50px;
height: 20px;
background-color: white;
margin: 10px;
z-index: 10000;
}
.childIWantOverOverlay {
background-color: red;
z-index: 12000;
}
<div class="parent">
<div class="subParent1">
<div class="child childIWantOverOverlay">child</div>
<div class="child">child</div>
<div class="child">child</div>
</div>
<!-- This component is underneat subParent in the tree structure -->
<div class="grayOverlay"></div>
</div>
UPDATE 2
Perhaps also consider use a pseudo-element for this, if it is acceptable in the actual use case.
This approach is more isolated, so it might be less likely to have conflict with other existing elements in the actual project.
Example with pseudo-element:
const btn = document.querySelector("button");
const divs = document.querySelectorAll("div.child");
let i = 0;
btn.addEventListener("click", () => {
divs[i].classList.toggle("selected");
if (i < 2) {
divs[i + 1].classList.toggle("selected")
i++;
return;
};
if (i >= 2) {
i = 0;
divs[i].classList.toggle("selected");
}
});
/* Can Change */
.parent {
width: 300px;
height: 300px;
position: relative;
}
/* 👇 Add this */
.parent::after {
content: "";
position: absolute;
inset: 0;
background-color: rgb(107 114 128 / 0.5);
z-index: 50;
}
/* 👇 Disabled for now
.grayOverlay {
position: absolute;
width: 100%;
height: 100%;
background-color: rgb(107 114 128 / 0.5);
z-index: 50;
}
*/
/* CANNOT CHANGE */
.subParent1 {
position: absolute;
display: flex;
flex-direction: column;
width: 100%;
}
/* Can Change */
.child {
color: black;
width: 50px;
height: 20px;
background-color: pink;
margin: 10px;
z-index: 25;
position: relative;
}
/* Can Change */
.selected {
background-color: red;
/* 👇 Add z-index */
z-index: 100;
}
button {
margin-bottom: 1em;
padding: 6px;
}
<button>Toggle</button>
<div class="parent">
<div class="subParent1">
<div class="subParent2">
<div class="child selected">child</div>
<div class="child">child</div>
<div class="child">child</div>
</div>
</div>
<!-- This component is underneat subParent in the tree structure. I cannot move this into subParent1 -->
<!-- <div class="grayOverlay"></div> -->
</div>
Update: also added position: relative on child.
It seems that this can be achieved by removing the z-index on grayOverlay and subParent1 (the grayOverlay is still stacked on top due to natural placement), and add some z-index on selected.
Example:
const btn = document.querySelector("button");
const divs = document.querySelectorAll("div.child");
let i = 0;
btn.addEventListener("click", () => {
divs[i].classList.toggle("selected");
if (i < 2) {
divs[i + 1].classList.toggle("selected")
i++;
return;
};
if (i >= 2) {
i = 0;
divs[i].classList.toggle("selected");
}
});
/* Can Change */
.parent {
width: 300px;
height: 300px;
position: relative;
}
/* Can Change */
.grayOverlay {
position: absolute;
width: 100%;
height: 100%;
background-color: rgb(107 114 128 / 0.5);
/* Removed z-index */
}
/* CANNOT CHANGE */
.subParent1 {
position: absolute;
display: flex;
flex-direction: column;
width: 100%;
/* Removed z-index */
}
/* Can Change */
.child {
color: black;
width: 50px;
height: 20px;
background-color: pink;
margin: 10px;
/* 👇 Add position */
position: relative;
}
/* Can Change */
.selected {
background-color: red;
/* 👇 Add z-index */
z-index: 100;
}
button {
margin-bottom: 1em;
padding: 6px;
}
<button>Toggle</button>
<div class="parent">
<div class="subParent1">
<div class="subParent2">
<div class="child selected">child</div>
<div class="child">child</div>
<div class="child">child</div>
</div>
</div>
<!-- This component is underneat subParent in the tree structure. I cannot move this into subParent1 -->
<div class="grayOverlay"></div>
</div>

How do I center my indicator items in a slider when the number images (items) is variable?

I have a slider that has the focus image centered but I'm having trouble centering the indicator items (dots) because each slider has a different number of images. Here is my HTML for the slider and the indicator:
<div class="main">
<section id="slider" >
<div class="container-fluid">
<div class = 'responsiveHeight'>
<div class = 'inner'>
<div class = 'iosSlider'>
<div class = 'slider'>
<img class="item selected" src="/park-terrace/00-park-terrace.jpg" alt="Park Terrace"/>
<img class="item " src="/park-terrace/01-park-terrace.jpg" alt="Park Terrace"/>
<img class="item " src="/park-terrace/02-park-terrace.jpg" alt="Park Terrace"/>
</div>
</div>
</div>
<div class="prevButton"></div>
<div class="nextButton"></div>
</div>
</div> <!-- /.container -->
<div class = 'indicators'>
<div class = 'item selected'></div>
<div class = 'item'></div>
<div class = 'item'></div>
</div>
</section>
Here is my CSS:
.main {height:432px;}
#slider {
position:absolute;
top:100px;
left:0px;
width:100%;
color:#666;
z-index:1;
}
.responsiveHeight {
height: 0;
padding: 0 0 80% 0;
position: relative;
overflow:hidden;
}
.responsiveHeight > .inner {
position: absolute;
width: 100%;
height: 100%;
}
.iosSlider {
width: 100%;
height: 100%;
}
.iosSlider .slider {
width: 100%;
height: 100%;
}
.iosSlider .slider img {
height: 100%;
padding-right:2px;
}
.indicators {
position: relative;
top: 10px;
left: 150px;
width: 400px;
height: 10px;
margin: 0 auto;
z-index: 10;
}
.indicators .item {
float: left;
width: 12px;
height: 12px;
margin: 0 5px 0 0;
border-radius: 10px;
background-color:#666;
}
An example of the problem is below:
small number of images
large number of images
I'm hoping there is a way to adjust my css rather than use javascript. I'm open to any suggestions and I appreciate your help.
If i'm understanding you correctly, we can isolate this down to just the 'indicators'. You can use flexbox to pop these in the center:
.indicators {
width: 100%;
display: flex;
justify-content: center;
padding: 40px 0;
}
.indicators .item {
width: 12px;
height: 12px;
margin: 0 5px 0 0;
border-radius: 10px;
background-color:#666;
}
<div class='indicators'>
<div class='item selected'></div>
<div class='item'></div>
<div class='item'></div>
</div>

One element's position is absolute, the other's position is relative, which one is the upper

I'm new in css. I confused in position. There is a simple example.
https://jsfiddle.net/4t8zn9yo/1/
$(document).ready(function() {
$('.content').scroll(function() {
if ($(this).scrollTop() > 0) {
if (!$('.topline').hasClass('long'))
$('.topline').addClass('long')
} else {
if ($('.topline').hasClass('long'))
$('.topline').removeClass('long')
}
});
});
.header {
position: relative;
height: 65px;
background: brown;
overflow-y: hidden;
overflow-x: hidden;
}
.topline {
position: absolute;
top: 0px;
width: 100vw;
height: 5px;
background: blue;
transition: 0.2s;
}
.topline.long {
height: 65px;
transition: 0.2s;
}
.topbar {
display: flex;
justify-content: center;
position: relative;
margin-top: 10px;
}
.topbar div {
flex: 1;
color: white;
}
.content {
height: calc(100vh - 65px);
overflow-y: auto;
overflow-x: hidden;
}
.content-parta {
height: 800px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class='header'>
<div class='topline'>
</div>
<div class='topbar'>
<div>test1</div>
<div>test2</div>
<div>test3</div>
<div>test4</div>
</div>
</div>
<div class='content'>
<div class='content-parta'>
</div>
</div>
When scroll event trigger, topline class is higher than topbar class. I have no idea why the son of topbar class is higher than topline class.
When I move the topline class after the topbar class, it is the highest.
I want to know why.
If you refer to the specification and the painting order:
All positioned, opacity or transform descendants, in tree order that fall into the following categories:
All positioned descendants with 'z-index: auto' or 'z-index: 0', in tree order.
For those with 'z-index: auto', treat the element as if it created a new stacking context, but any positioned descendants and descendants which actually create a new stacking context should be considered part of the parent stacking context, not this new one.
Both elements are positionned with the same properties (z-index:auto is the important one) so the tree order will decide which one will be on the top. In your actual code topbar is on the top. If you switch the HTML order you will have it on the bottom:
$(document).ready(function() {
$('.content').scroll(function() {
if ($(this).scrollTop() > 0) {
if (!$('.topline').hasClass('long'))
$('.topline').addClass('long')
} else {
if ($('.topline').hasClass('long'))
$('.topline').removeClass('long')
}
});
});
.header {
position: relative;
height: 65px;
background: brown;
overflow-y: hidden;
overflow-x: hidden;
}
.topline {
position: absolute;
top: 0px;
width: 100vw;
height: 5px;
background: blue;
transition: 0.2s;
}
.topline.long {
height: 65px;
transition: 0.2s;
}
.topbar {
display: flex;
justify-content: center;
position: relative;
margin-top: 10px;
background:red;
}
.topbar div {
flex: 1;
color: white;
}
.content {
height: calc(100vh - 65px);
overflow-y: auto;
overflow-x: hidden;
}
.content-parta {
height: 800px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class='header'>
<div class='topline'>
</div>
<div class='topbar'>
<div>test1</div>
<div>test2</div>
<div>test3</div>
<div>test4</div>
</div>
</div>
<div class='content'>
<div class='content-parta'>
</div>
</div>
If you remove the position from one element, whataver the tree order the other positionned element will always be on the top.
$(document).ready(function() {
$('.content').scroll(function() {
if ($(this).scrollTop() > 0) {
if (!$('.topline').hasClass('long'))
$('.topline').addClass('long')
} else {
if ($('.topline').hasClass('long'))
$('.topline').removeClass('long')
}
});
});
.header {
position: relative;
height: 65px;
background: brown;
overflow-y: hidden;
overflow-x: hidden;
}
.topline {
position: absolute;
top: 0px;
width: 100vw;
height: 5px;
background: blue;
transition: 0.2s;
}
.topline.long {
height: 65px;
transition: 0.2s;
}
.topbar {
display: flex;
justify-content: center;
margin-top: 10px;
background:red;
}
.topbar div {
flex: 1;
color: white;
}
.content {
height: calc(100vh - 65px);
overflow-y: auto;
overflow-x: hidden;
}
.content-parta {
height: 800px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class='header'>
<div class='topline'>
</div>
<div class='topbar'>
<div>test1</div>
<div>test2</div>
<div>test3</div>
<div>test4</div>
</div>
</div>
<div class='content'>
<div class='content-parta'>
</div>
</div>
Related:
Why can't an element with a z-index value cover its child?
Why does position:relative; appear to change the z-index?
HTML thinks that it is now behind. Think of it as a 3 dimensional environment. You can use z-index. This way you can control how the appearance works. You can check this out.

How to place this div at the bottom of the document?

The document has a structure like this :
<body>
<div>
<div>
content here
</div>
</div>
<div class="page">
<div class="nav-bar">
<div class="nav-bar-inner padding10" >
<span style="text-align: center;" >
2015, XXX © by <a class="fg-color-white" href="mailto:xxx#xxx.com">XXX</a>
</span>
</div>
</div>
</div>
</body>
CSS are these :
.metrouicss {
}
.metrouicss .page {
position: relative;
height: 100%;
min-height: 100%;
width: 100%;
*zoom: 1;
}
.metrouicss .page {
width: 940px ;
margin: auto;
background-color: #fff;
}
.metrouicss .nav-bar {
background-color: #2d89ef;
position: relative;
top: 0;
width: 100%;
display: block;
margin: 0;
padding: 0;
z-index: 1000;
*zoom: 1;
}
.metrouicss .nav-bar .nav-bar-inner {
*zoom: 1;
}
.padding10 {
padding: 10px;
}
At runtime the <div class="page"> after the content is just below the content ! I want it to be at the bottom of the document. How to do that ?
Here is a good tutorial how to keep block at the bottom of the page http://matthewjamestaylor.com/blog/keeping-footers-at-the-bottom-of-the-page
Basically you just need to add a few styles to your block :
.metrouicss .page {
position : absolute;
bottom : 0;
}
You could add a few empty divs in between, you could add bottom margins under the content or top margins where the mail link div is.

html/css full background overlay div inside another div

I have a simple < div > (without fixed hegiht) with a text in it:
<div id="section">
<div class="container">
<h1>text</h1>
<p>More text</p>
</div>
<!-- <div id="overlay"></div> -->
</div>
The CSS for this is something like:
#section {
background: red;
overflow: hidden;
}
It's possibile to add a div with a transparent image background?
The overlay sholud be hover the main red background, but under the text.
I think is something like this, but dont works:
#section #overlay {
position: relative;
top: 0px;
left: 0px;
width: 100%;
height: 100px; /* ??? */
background: green;
opacity: 0.1;
}
#section {
background: red;
display: block;
position: relative;
overflow: hidden;
}
#container {
position: relative;
width: 100%;
text-align: center;
z-index: 9999;
}
#overlay {
position: absolute;
left: 0;
width: 100%;
height: 100%;
top: 0;
background-color: rgba(0,0,0,0.3);
}
If I'm understanding you correctly, how about something like this:
HTML:
<div id="section">
<div id="container">
<h1>My background is transparent!</h1>
<p>More text</p>
</div>
</div>
CSS:
#section {
width: 300px;
background-color: red;
}
#container {
position: relative;
left: 50px;
width: 200px;
text-align: center;
background-color: rgba(0,0,0,0.3);
}
Results here: JSFiddle
If that's not what you wanted, can you be more specific about the positioning?
try below example using jquery ui will reduce the effort
<div id="dialog">Your non-modal dialog</div>
Open dialog
$('#open').click(function() {
$('#dialog').dialog('open');
});
jQuery(document).ready(function() {
jQuery("#dialog").dialog({
autoOpen: false,
modal: true,
open: function(){
jQuery('.ui-widget-overlay').bind('click',function(){
jQuery('#dialog').dialog('close');
})
}
});
});

Resources