Moving around between <nav>, <section> and <main> - css

I am able to divide the whole page into 4 regions and they are:-
[header] (on the very top), [nav] (right below the header), [section] (on the bottom left) and [main] (on the bottom right).
In the [nav] portion, I have a list of hyperlinked items (like “item-A”, “item-B”, etc).
The task is to:-
When “item-A” is selected, the corresponding sub-list containing “A1”, “A2”, “A3” etc should be displayed on the [section] part. Similarly, if “item-B” is selected, the sub-list “B1”, “B2” should also be displayed on the [section] part (overwriting the previous content, of course).
“B2” again is hyperlinked to the file “B.html” which, when called, should be executed on the [main] portion.
How can I do all of the above?
P.S. I can finish the above if I use [frame] and [frameset]. Unfortunately, these become obsolete in HTML5.
The widths and heights of each region can be defined inside the CSS setup.

You can use buttons instead of a hyperlink and get the same output.
Below is my solution:
const displayItemA = () => {
document.getElementById("item-A").style.display = 'grid';
document.getElementById("item-B").style.display = 'none';
}
const displayItemB = () => {
document.getElementById("item-B").style.display = 'grid';
document.getElementById("item-A").style.display = 'none';
}
const mainContent = ["A1", "A2", "A3", "B1", "B2", "B3"];
const displayMain = (q) => {
document.getElementById(q).style.display = "grid";
const toNone = mainContent.filter(e => e !== q);
for (let i = 0; i < toNone.length; i++) {
document.getElementById(toNone[i]).style.display = "none";
}
}
const displayA1 = () => displayMain("A1");
const displayA2 = () => displayMain("A2");
const displayA3 = () => displayMain("A3");
const displayB1 = () => displayMain("B1");
const displayB2 = () => displayMain("B2");
const displayB3 = () => displayMain("B3");
:root {
--main-color:red;
--dark-color:#444;
}
* {
margin:0;
padding:0;
box-sizing:border-box;
}
body {
margin: 0px;
display: grid;
place-items: center;
font-size: 20px;
}
/* repeated element */
.button-nav {
text-decoration: none;
color: var(--main-color);
background: none;
border: none;
font-size: 20px;
text-align: start;
}
.header {
height: 100px;
width: 100%;
display: grid;
place-items: center;
border-bottom: 2px solid var(--dark-color);
}
.nav {
position: relative;
height: 75px;
width: 100%;
border-bottom: 2px solid var(--dark-color);
display: flex;
align-items: center;
justify-content: center;
gap: 1em;
}
.nav h2 {
position: absolute;
left: 30px;
}
.section {
position: absolute;
left: 0px;
min-height: calc(100vh - 175px);
width: 30%;
border-right: 2px solid var(--dark-color);
padding: 30px;
gap: 1em;
}
.sub-nav {
display: grid;
gap: 1em;
}
#item-A, #item-B{ display:none }
.main {
position: absolute;
left: 30%;
min-height: calc(100vh - 175px);
width: 70%;
display: grid;
padding: 30px;
gap: 1em;
text-align: center;
}
#A1 { display: grid; }
#A2, #A3, #B1, #B2, #B3 { display: none; }
<header class="header">
<h1>Header</h1>
</header>
<nav class="nav">
<h2>Nav</h2>
<button class="button-nav" onclick="displayItemA()">item-A</button>
<button class="button-nav" onclick="displayItemB()">item-B</button>
</nav>
<div>
<section class="section">
<h3>Section</h3>
<br />
<nav class="sub-nav" id="item-A">
<button class="button-nav" onclick="displayA1()">A1</button>
<button class="button-nav" onclick="displayA2()">A2</button>
<button class="button-nav" onclick="displayA3()">A3</button>
</nav>
<nav class="sub-nav" id="item-B">
<button class="button-nav" onclick="displayB1()">B1</button>
<button class="button-nav" onclick="displayB2()">B2</button>
<button class="button-nav" onclick="displayB3()">B3</button>
</nav>
</section>
<main class="main">
<h3>Main</h3>
<div id="A1">These are the contents of A1.</div>
<div id="A2">These are the contents of A2.</div>
<div id="A3">These are the contents of A3.</div>
<div id="B1">These are the contents of B1.</div>
<div id="B2">These are the contents of B2.</div>
<div id="B3">These are the contents of B3.</div>
</main>
</div>
You can also test the code at enter link description here so you can see it on a larger viewport.
Update: I made the items in the "section" area blank by default as per the OP's request. This was done by changing the value of the display of "#item-A" to "none" in the CSS file.

Stack Blitz code:
https://stackblitz.com/edit/web-platform-uwbmw4?devtoolsheight=33&file=index.html
Because it needs a1,a2,b1,b2 HTML files and stuffs it does not work here(below)(other parts work other than iframe stuff) please try above stackblitz for testing
const itemAOptions = [
{
name: 'A1',
data: 'A1.html',
},
{
name: 'A2',
data: 'A2.html',
},
];
const itemBOptions = [
{
name: 'B1',
data: 'B1.html',
},
{
name: 'B2',
data: 'B2.html',
},
];
const dataContainer = document.querySelector('#display');
const menuContainer = document.querySelector('#menu');
const navContainer = document.querySelector('#navBar');
navContainer.addEventListener('click', (e) => {
e.stopPropagation();
if ('nochange' in e.target.dataset) {
e.preventDefault();
const toLoad = e.target.dataset.nochange;
let data = '';
if (toLoad === 'loadA') {
data = constructData(itemAOptions);
} else {
data = constructData(itemBOptions);
}
menuContainer.innerHTML = data;
display.innerHTML = ``;//emptydata means clear or empty screen as you requested
}
});
menuContainer.addEventListener('click', (e) => {
e.stopPropagation();
e.preventDefault();
const toLoad = e.target;
let data = '';
data = `<iframe src="https://web-platform-uwbmw4.stackblitz.io/${toLoad.innerHTML}.html" name="targetframe" allowTransparency="true" scrolling="no" frameborder="0" >
</iframe>`;//use src="Your.Website.address.or.directory/${toLoad.innerHTML}.html"
console.log(toLoad.innerHTML);
display.innerHTML = data;
});
function constructData(item) {
let innerData = '';
item.forEach((i) => {
innerData += `<li class="li">${i.name}</li>`;
});
return `<ul class="ul">${innerData}</ul>`;
}
function constructDataIframe(item) {
let innerData = '';
item.forEach((i) => {
innerData += `<iframe src="https://web-platform-uwbmw4.stackblitz.io/${i.data}" name="targetframe" allowTransparency="true" scrolling="no" frameborder="0" >
</iframe>`;
});
return `${innerData}`;
}
h1 {
text-align:center;
}
#navBar{
background-color: transparent;
border: 5px solid black;
text-align: center;
}
.lk{
text-decoration: none;
}
.uli{
display: flex;
justify-content: flex-end;
}
.lik{
list-style: none;
padding-right:15px;
}
.a{
text-decoration: none;
}
.li{
list-style: none;
}
.ul{
float:left;
padding-left: 10px;
}
#secHolder{
width: 100%;
background-color: transparent;
border: 5px solid black;
text-align: center;
}
#display{
width: 100%;
background-color: transparent;
border: 5px solid black;
text-align: center;
}
#Holder{
width: 100%;
display: flex;
flex-direction: row;
justify-content: center;
}
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
<h1>Header</h1>
<nav id="navBar">
<ul>
<div class="uli">
<li class="lik">Item A</li>
<li class="lik">Item B</li>
</div>
</ul>
</nav>
<div id="Holder">
<div id="secHolder">
<h3>Section</h3>
<section id="menu"></section>
</div>
<main id="display"></main>
</div>
<script src="script.js"></script>
</body>
</html>
P.S I have tried my best on answering but I don't have regular practice on commenting please try to understand, ask for doubts.
I cannot understand what you mean by I cannot use frame its obsolete in html5, I have used iframe is it ok?

I didn't concentrate on stylings. It is recommended to use iframe instead of object tag. You can try exploring that as well.
const itemAOptions = [{
name:"A1",
data:"A1.html"
}, {
name:"A2",
data:"A2.html"
}];
const itemBOptions = [{
name:"B1",
data:"B1.html"
}, {
name:"B2",
data:"B2.html"
}];
const dataContainer = document.querySelector("#display");
const menuContainer = document.querySelector("#menu");
const navContainer = document.querySelector("#navBar");
navContainer.addEventListener("click", (e)=>{
e.stopPropagation();
if("nochange" in e.target.dataset){
e.preventDefault();
const toLoad = e.target.dataset.nochange;
let data = '';
if(toLoad === "loadA"){
data = constructData(itemAOptions);
}
else{
data = constructData(itemBOptions);
}
menuContainer.innerHTML = data;
}
});
menuContainer.addEventListener("click", (e)=>{
e.stopPropagation();
if("spaload" in e.target.dataset){
e.preventDefault();
const data = e.target.dataset.spaload;
dataContainer.innerHTML=`<object type="text/html" data=${data} ></object>`;
}
});
function constructData(item){
let innerData = '';
item.forEach((i)=>{
innerData+=`<li><a href=${i.data} data-spaload=${i.data}>${i.name}</a></li>`;
});
return `<ul>${innerData}</ul>`;
}
<nav id="navBar">
<ul>
<li>Item a</li>
<li>Item B</li>
</ul>
</nav>
<h3>Section</h3>
<section id="menu"></section>
<main id="display"></main>

const embed = document.getElementById("main-frame");
const navLinksContainer = document.getElementById("nav-links");
const subLinksContainer = document.getElementById("sub-links");
const pageLinks = {
"item-A": {
A1: "https://en.wikipedia.org/wiki/Australia",
A2: "https://en.wikipedia.org/wiki/Austria",
A3: "https://en.wikipedia.org/wiki/America",
},
"item-B": {
B1: "https://en.wikipedia.org/wiki/Barbados",
B2: "https://en.wikipedia.org/wiki/Bahamas",
B3: "https://en.wikipedia.org/wiki/Brazil",
},
"item-C": {
C1: "https://en.wikipedia.org/wiki/Canada",
C2: "https://en.wikipedia.org/wiki/Cayman_Islands",
C3: "https://en.wikipedia.org/wiki/Chile",
},
};
// Creates the page link element
function createPageLink(text, href = "") {
const listItem = document.createElement("LI");
const anchor = document.createElement("A");
anchor.innerHTML = text;
anchor.href = href;
listItem.appendChild(anchor);
listItem.anchor = anchor;
return listItem;
}
window.onload = function loadHandler() {
// build all the sub links for each nav link.
Object.keys(pageLinks).forEach((text) => {
const subSectionLinks = Object.keys(pageLinks[text]).map((subText) => {
const subLink = createPageLink(subText, pageLinks[text][subText]);
subLink.anchor.addEventListener("click", function (event) {
event.preventDefault();
embed.src = event.target.href;
});
return subLink;
});
// replaces the sub links in the left section
// for each corresponding nav link that's clicked.
const navLink = createPageLink(text);
navLink.anchor.addEventListener("click", function (event) {
event.preventDefault();
subLinksContainer.innerHTML = "";
subSectionLinks.forEach((element) =>
subLinksContainer.appendChild(element)
);
embed.src = "";
});
navLinksContainer.appendChild(navLink);
});
};
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
ul {
list-style-type: none;
}
a {
text-decoration: none;
color: red;
font-size: 28px;
}
a:hover {
color: #920000;
}
body {
font-family: Arial, Helvetica, sans-serif;
font-weight: bold;
font-size: 32px;
color: #222;
}
.page {
width: 702px;
height: 918px;
margin: 50px auto;
display: grid;
gap: 0;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(10, 1fr);
grid-template-areas:
"h h h h"
"h h h h"
"n n n n"
"s m m m"
"s m m m"
"s m m m"
"s m m m"
"s m m m"
"s m m m"
"s m m m";
}
.page > * {
border: 1px solid #777;
}
.page > header {
grid-area: h;
display: flex;
justify-content: center;
align-items: center;
}
.page > nav {
grid-area: n;
display: flex;
flex-direction: row;
align-items: center;
}
.page > section {
grid-area: s;
text-align: center;
padding-top: 15px;
}
.page > main {
grid-area: m;
text-align: center;
}
.page > nav div {
width: 25%;
text-align: center;
}
.page > nav ul {
width: calc(100% - 25%);
text-align: center;
}
.page > nav ul li {
display: inline;
}
.page > nav ul li:nth-of-type(n + 2) {
margin-left: 15px;
}
.page > section ul {
margin-top: 50px;
text-align: left;
text-indent: 40px;
}
.page > section ul li {
margin-bottom: 10px;
}
.page > main p {
height: 8%;
margin-top: 20px;
}
.page > main iframe {
width: 100%;
height: calc(92% - 20px);
border: none;
overflow-x: hidden;
}
<div class="page">
<header>Header</header>
<nav>
<div>nav</div>
<ul id="nav-links"></ul>
</nav>
<section>
section
<ul id="sub-links"></ul>
</section>
<main>
<p>main</p>
<iframe allowTransparency="true" id="main-frame"></iframe>
</main>
</div>
Update:
I added a line of code to clear the iframe whenever the user selects a different link from the navigation bar as per the comments made by the OP.

Related

When click on sidebar menu in right side routes page display

I have sideNavbar and when click on side bar menu return menu componetns on the right side.
Below i have mention the image just look same output want.
Sandboxlink:https://m7tqt3.csb.app/
SideNavbar.js
---
import "./SideNavBar.css";
const SideNavBar = () => {
const menuItems = [
{
text: "Dashboard",
icon: "icons/grid.svg",
},
{
text: "Admin Profile",
icon: "icons/user.svg",
},
{
text: "Messages",
icon: "icons/message.svg",
},
{
text: "Analytics",
icon: "icons/pie-chart.svg",
},
{
text: "File Manager",
icon: "icons/folder.svg",
},
{
text: "Orders",
icon: "icons/shopping-cart.svg",
},
{
text: "Saved Items",
icon: "icons/heart.svg",
},
{
text: "Settings",
icon: "icons/settings.svg",
},
];
return (
<div
className={
"side-nav-container"
}
>
<div className="nav-upper">
<div className="nav-heading">
(
<div className="nav-brand">
<img src="icons/Logo.svg" alt="" srcset="" />
<h2>Showkart</h2>
</div>
)
</div>
<div className="nav-menu">
{menuItems.map(({ text, icon }) => (
<a
className={ "menu-item"}
href="#"
>
<img className="menu-item-icon" src={icon} alt="" srcset="" />
{ <p>{text}</p>}
</a>
))}
</div>
</div>
</div>
);
};
export default SideNavBar;
SideNavbar.css
/* NX = not expanded */
.side-nav-container {
background-color: var(--dark);
width: 300px;
height: 100vh;
position: relative;
color: var(--light);
transition: 0.4s;
}
.side-nav-container-NX {
width: 85px;
}
.nav-upper,
.nav-heading,
.nav-menu,
.menu-item,
.nav-footer {
/* border: 2px solid white; */
display: grid;
}
.nav-heading {
grid-template-columns: 2fr 1fr;
grid-template-rows: 1fr;
height: 75px;
}
.nav-brand {
display: flex;
color: var(--light);
}
.nav-brand img {
width: 40px;
padding: 0 10px;
}
.hamburger {
background: none;
border: none;
cursor: pointer;
margin: auto;
}
.hamburger span {
display: block;
margin-top: 5px;
background-color: var(--light);
border-radius: 15px;
height: 5px;
width: 35px;
transition: 0.4s;
}
.hamburger:hover span {
background-color: var(--primary);
}
.hamburger-in:hover span:nth-child(1) {
width: 25px;
transform: translateY(4px) rotate(-25deg);
}
.hamburger-in:hover span:nth-child(2) {
width: 40px;
}
.hamburger-in:hover span:nth-child(3) {
width: 25px;
transform: translateY(-4px) rotate(25deg);
}
/* ///////////////////// */
/* ///////////////////// */
/* ///////////////////// */
/* ///////////////////// */
.hamburger-out {
margin-left: 24px;
}
.hamburger-out:hover span:nth-child(1) {
width: 25px;
transform: translate(14px, 4px) rotate(-155deg);
}
.hamburger-out:hover span:nth-child(2) {
width: 40px;
}
.hamburger-out:hover span:nth-child(3) {
width: 25px;
transform: translate(14px, -4px) rotate(155deg);
}
.nav-menu {
grid-template-rows: repeat(7, 1fr);
margin-top: 50px;
}
.menu-item {
height: 57px;
display: flex;
color: var(--light);
text-decoration: none;
text-transform: uppercase;
margin: auto 20px;
border-radius: 10px;
}
.menu-item-NX {
margin: auto;
}
.menu-item:hover {
background-color: var(--primary);
}
.menu-item img {
width: 30px;
padding: 0 20px;
}
.nav-footer {
width: 100%;
height: 87px;
position: absolute;
bottom: 0;
grid-template-rows: 1fr;
grid-template-columns: 2fr 1fr;
}
.nav-details {
display: flex;
}
.nav-details img {
width: 50px;
padding: 0 20px;
}
.nav-footer-user-name {
font-size: 18px;
font-weight: 900;
}
.nav-footer-user-position {
margin-top: -15px;
color: var(--gray);
}
.logout-icon {
width: 30px;
margin: auto;
border-radius: 90px;
padding: 20px;
margin-left: 5px;
}
.logout-icon:hover {
background-color: var(--primary);
}
Notes: React router dom version: 5.3.1.
Output look like:
enter image description here
Routes to another components on right side
Firstly, if I undestand your question, you want a side navbar which allows you to navigate to different pages with your react app. If so:
<div className="nav-menu">
{menuItems.map(({ text, icon }) => (
<a <--- The problem is here
className={ "menu-item"}
href="#"
>
<img className="menu-item-icon" src={icon} alt="" srcset="" />
{ <p>{text}</p>}
</a>
))}
</div>
You are using anchor tag which will redirect you out of react router. You should use Link tag which allows to redirect to different pages within your react app.
const menuItems = [
{
text: "Dashboard",
icon: "icons/grid.svg",
navLink:'/dashboard'
},
{
text: "Admin Profile",
icon: "icons/user.svg",
navLink:'/admin'
},...]
<div className="nav-menu">
{menuItems.map(({ text, icon, navlink }) => (
<Link
className={ "menu-item"}
to={navlink}
>
<img className="menu-item-icon" src={icon} alt=""
srcset=""
/>
{ <p>{text}</p>}
</Link>
))}
</div>
Likewise you need to step up your App.js with BrowserRouter, Routes and Route to move between pages.

Vue dynamically changing background position

I have a list of items that are background-image and I need to go down through each item down (-38px) and display all of them changing only the background-position
enter image description here
Should be displayed in a line
enter image description here
My vue code:
CraftPage:
<template>
<div class="page-wrap">
<my-nav-craft/>
<div class="wrap">
<div class="construct">
<div class="left">
<h3 class="title">Basic</h3>
<ul class="items">
<my-li-crafts :items="items"/>
</ul>
</div>
</div>
</div>
</div>
</template>
<script>
import MyNavCraft from "#/components/navCraft/navCraft";
import MyLiCrafts from "#/components/navCraft/liCraft";
export default {
components: {MyLiCrafts, MyNavCraft},
data() {
return {
items: [
{id: 1, posX: 0, posY: 0},
{id: 2, posX: 0, posY: -38}
]
}
},
}
</script>
<style scoped>
.page-wrap{
width: 100%;
display: flex;
flex-direction: column;
max-width: 1200px;
justify-content: center;
margin: 0px auto;
}
.wrap {
width: 100%;
background-color: #c6c6c6;
border-radius: 20px;
padding: 26px 23px 8px;
}
.left {
float: left;
width: 340px;
clear: both;
margin-bottom: 5px;
}
.items{
list-style: none;
}
.items__item {
background-image: url("../assets/icon_sprite.png");
width: 36px;
height: 36px;
margin-right: 5px;
margin-bottom: 5px;
cursor: pointer;
}
</style>
My element which needs to change background-position to -38px
My-li-craft:
<template>
<li class="items__item" v-for="item in items" :key="item.id"
:style="{backgroundPosition: item.posX + 'px' + ' ' + item.posY + 'px' }"
>
</li>
</template>
<script>
export default {
name: "my-li-crafts",
props: {
items: {
type: Array,
required: true
}
},
data() {
return {
}
},
methods: {
bgPos: function () {
let el = this.$el.querySelector('.items__item'), bgWidth = 20, bgHeight = 20;
for (let i = 0; i< 3; i++) {
return el.css({
"background-position": (el.width()-bgWidth+10) + "px " + (el.height()-bgHeight-10) + "px"
})
}
}
},
// computed: {
// bgPoss: function () {
// const el = this.$el.querySelector('.items__item'), bgWidth = 20, bgHeight = 20;
// return el.css({
// "background-position": (el.width()-bgWidth+10) + "px " + (el.height()-bgHeight-10) + "px"
// })
//
// }
// }
}
</script>
<style scoped>
.items__item {
background-image: url("../../assets/icon_sprite.png");
width: 36px;
height: 36px;
margin-right: 5px;
margin-bottom: 5px;
cursor: pointer;
}
</style>

CSS Grid - Content overlapping issue

Is it possible to create the following layout using CSS grid?
The layout itself is pretty straightforward. Here's what I have so far:
HTML:
<div class="sidebar__wrapper">
<div class="sidebar__item mb-1" [class.mt-3]="item.options.length"
*ngFor="let item of sidebarItems; let first = first;">
<div class="sidebar__icon ark-cursor-pointer" [class.align-self]="item.options.length" (click)="item.isExpand = !item.isExpand">
<img [src]="item.icon" alt="icon" [class.valign--middle]="item.options.length">
</div>
<div class="sidebar__label font--14">
<div *ngIf="!showItemTitle"></div>
<a class="sidebar__header pl-1" [routerLink]="item.stateName" [class.font--light]="!item.options.length" [ngClass]="{'font--11 text-uppercase sidebar__header--blue' : item.options.length}" (click)="item.isExpand = !item.isExpand"
*ngIf="showItemTitle">{{ 'Sidebar.' + item.property + '.Title' | translate}}</a>
<ng-container *ngFor="let subItem of item.options; let first = first">
<a class="sidebar__subheader pl-1" [routerLink]="subItem.stateName" [class.mt-2]="first"
*ngIf="showItemTitle && item.isExpand" [ngClass]="hasActiveChild(subItem)"><span>{{ 'Sidebar.' + item.property +'.'+ subItem.subtitle | translate}}</span></a>
</ng-container>
</div>
</div>
CSS:
.sidebar__wrapper,
.sidebar__item,
.sidebar__label {
display: grid;
}
.sidebar__wrapper {
align-items: flex-start;
grid-template-columns: 100%;
}
.sidebar__item {
/* grid-template-columns: 20px auto 20px; */
grid-template-columns: 20px auto;
margin: 0 15px 0 8px;
align-items: center;
column-gap: 5px;
}
.sidebar__label {
align-items: center;
row-gap: .5rem;
grid-template-columns: 100%;
grid-auto-rows: 23px;
}
.font--14 {
font-size: 14px;
}
.font--11 {
font-size: 11px;
}
.sidebar__header {
font-weight: var(--bold-font-weight);
}
.sidebar__subheader {
font-weight: var(--light-font-weight);
}
.sidebar__icon {
justify-self: center;
}
.sidebar__icon img {
height: 15px;
width: auto;
vertical-align: unset;
}
#side-bar a {
text-decoration: none;
list-style-type: none;
color: #FFFFFF;
}
#side-bar .active-text-bold {
background-color: rgba(104, 131, 158, 0.31);
border-radius: 5px;
padding: .25em .125rem;
width: calc(100% + 5px);
}
.align-self {
align-self: flex-start;
}
.valign--middle {
vertical-align: middle !important;
}
.sidebar__header--blue {
color: rgba(111,140,169, 0.8) !important;
}
The object sidebarItems looks as such:
const sidebarItems = [
{
icon: 'assets/images/icon/sidebar_time.png',
isExpand: false,
title: 'Gestion du temps',
property: 'TimeManagement',
stateName: '/time/stats',
options: [
{
subtitle: 'AccountChart',
stateName: '/accounting/accounts'
}
]
},
{
icon: 'assets/images/icon/sidebar_contacts.png',
property: 'Contact',
isExpand: true,
stateName: '/contacts/list',
options: []
}
];
hasActiveChild(item) {
let className = '';
if (location.pathname.includes(item.stateName)) {
className = 'active-text-bold';
}
return className;
}
The above code creates the following layout:
However, I'm unable to re-create the spacing on the left of each sub-item.
I've tried to name the grid lines and set the grid-column: 2/4. It somehow messes up the layout.
If you have some ideas on how I can solve this issue, please let me know. Thank you.
Thanks.
Please look into the CSS padding property.
In your case, adding a left padding to the links should do.
Try this:
.sidebar__item {
/* grid-template-columns: 20px auto 20px; */
grid-template-columns: 20px auto;
margin: 0 15px 0 8px;
align-items: center;
column-gap: 5px;
padding-left: 5px;
}

changing CSS of element on page scroll

I have a fixed header component as the two pics below illustrate. The current styling that I have is fine for when the page loads and nothing has changed. However, I want the header to have a visible border-bottom of say 1px solid black as soon as the user starts to scroll down the page. So in this case, this styling change would apply to the second pic. How can I accomplish this?
header on page load:
header on scroll:
Header.js:
const Header = props => {
return (
<header className="header-container">
<div className="logo-container">
<img className="white-logo" src={logo} alt="Food Truck TrackR logo white" />
</div>
<section className="header-section-one">
<div className="location-sub-div">
<i class="fas fa-map-marker-alt"></i>
<h3>User Location</h3>
</div>
<div className="order-sub-div">
<i class="fas fa-store"></i>
<h3>Order now</h3>
</div>
</section>
<section className="header-section-two">
<NavLink to="/dine/search" className="search-sub-div">
<i class="fas fa-search search-icon"></i>
<h3>Search</h3>
</NavLink>
<div className="acct-sub-div">
<i class="fas fa-user acct-icon"></i>
<h3>Account</h3>
</div>
</section>
</header>
)
}
Header.scss:
.header-container {
width: 100%;
height: 9vh;
display: flex;
align-items: center;
color: black;
background: white;
font-size: 0.6rem;
padding-left: 4%;
padding-right: 4%;
position: fixed;
top: 0;
// border-bottom: 1px solid black;
z-index: 99;
}
.logo-container {
width: 20%;
margin-right: 6%;
.white-logo {
width: 100%;
}
}
.header-section-one {
width: 32%;
display: flex;
margin-right: 25%;
justify-content: space-evenly;
.location-sub-div {
display: flex;
h3 {
width: 100%;
white-space: nowrap;
}
}
.order-sub-div {
display: flex;
h3 {
white-space: nowrap;
}
}
}
.header-section-two {
width: 32%;
display: flex;
justify-content: space-evenly;
.search-sub-div {
display: flex;
.search-icon {
margin-right: 1%;
}
}
.acct-sub-div {
display: flex;
.acct-icon {
margin-right: 1%;
}
}
}
i {
margin-right: 1% !important;
}
This neat CSS trick might help you with the problem:
html:not([data-scroll='0']) {
.header-container {
width: 100%;
height: 9vh;
display: flex;
align-items: center;
color: black;
background: white;
font-size: 0.6rem;
padding-left: 4%;
padding-right: 4%;
position: fixed;
top: 0;
border-bottom: 1px solid black;
z-index: 99;
}
}
Here is a, link further explaining the solution: https://css-tricks.com/styling-based-on-scroll-position/
Good luck.
You can add an event listener to the document, and when a scroll event is fired, you can check to see what the vertical scroll position (scrollTop) of the document is, and conditionally show a border based on that value.
Here's an example:
import React, { useEffect, useState } from "react";
const Header = () => {
// Store a bool that determines if the border is visible
const [isBorderVisible, setIsBorderVisible] = useState(false);
useEffect(() => {
// Define a function that is called when the scroll event fires
const handleScroll = e => {
const scrollTop = e.target.documentElement.scrollTop;
if (scrollTop > 200) {
setIsBorderVisible(true);
} else {
setIsBorderVisible(false);
}
};
// Add the event listener inside a useEffect
if (document) {
document.addEventListener("scroll", handleScroll);
}
// Remove the event listener on unmount
return () => {
if (document) {
document.removeEventListener("scroll", handleScroll);
}
};
}, [setIsBorderVisible]);
return (
<div
style={{
position: "fixed",
top: 0,
left: 0,
right: 0,
height: "100px",
background: "hotpink",
// Conditionally style the border
borderBottom: isBorderVisible ? "2px solid #000" : "0"
}}
/>
);
};
So we have a useEffect, that adds an event listener to the document, listening for the scroll event. Whenever a scroll occurs, the handleScroll function (also defined inside the useEffect) fires.
In this function, we get the scrollTop value, which is the number of pixels that have been scrolled from the top of the document.
In the example, we are setting the state value isBorderVisible to true once we have a scrollTop greater than 200 pixels, but this can be anything you want.
In the header's style, we conditionally set a border, based on the state value of isBorderVisible.

How to set the content of div to be visible inside parent div using css

i want the content inside the expandable_container div to be visible.
Now it moves up while adding align-items: center to the expandable div.
I have a side panel which contains list items. when the list item overflows i add a expand button. clicking that button should show the full content of list item. It works but then. when the content in list item overflows then the content in list item is half seen. like in below image
i want that content to properly placed. I tried adding padding-top to expandable class. However this will affect other list items that doesnt have expandable component. How can i fix this. Below is the code,
export default class Expandable extends React.PureComponent{
constructor(props) {
super(props);
this.expandable_ref = React.createRef();
this.state = {
expanded: false,
overflow: false,
};
}
componentDidMount () {
if (this.expandable_ref.current.offsetHeight <
this.expandable_ref.current.scrollHeight) {
this.setState({overflow: true});
}
}
on_expand = () => {
this.setState({expanded: true});
console.log("in expnad");
};
on_collapse = () => {
this.setState({expanded: false});
};
render () {
return (
<div className={(this.state.overflow ?
this.props.container_classname : '')}>
<div className={(this.state.overflow ?
this.props.classname : '')} style={{overflow: 'hidden',
display: 'flex', height: (this.state.expanded ? null :
this.props.base_height)}}
ref={this.expandable_ref}>
{this.props.children}
</div>
{this.state.overflow && this.state.expanded &&
<div className={this.props.expand}>
<button onClick={this.on_collapse}>
{this.props.arrow_up}</button>
</div>}
{this.state.overflow && !this.state.expanded &&
<div className={this.props.expand}>
<button onClick={this.on_expand}>
{this.props.arrow_down}</button>
</div>}
</div>
);
}
}
Class SidePanel extends React.purecomponent {
switch (notification.type) {
case 'new_model_uploaded':
return (
<Expandable
base_height={42}
arrow_down={<SvgAccDown className='grey' width="10"
height="10"/>}
arrow_up={<SvgAccUp className='grey' width="26"
height="26"/>}
container_classname='expandable_container'
classname='expandable'
expand='expand'>
<ListItem
icon={<SvgProject width="26" height="26"/>}
text={<Text
name={notification.initiator.name}
text=' created model '
model_name={notification.attributes.modelname}/>}
timestamp={notification.timestamp}>
<div className="additional_details">
<PreviewImage
width={70}
height={70}
model_id={filtered_model.id}
/>
</div>
</ListItem>
</Expandable>
);
case 'deleted':
return (
<ListItem
icon={<Svg width="20" height="22"/>}
text={<Text
name={notification.initiator.name}
text=' deleted model '
model_name={notification.attributes.modelname}/>}
timestamp={notification.timestamp}/>
);}
}
function ListItem(props) {
return (
<li className="notification">
<div className="details_container">
<div className="details">
{props.icon}
{props.text}
<Timestamp>{props.timestamp}</Timestamp>
</div>
{props.children}
</div>
</li>
);
}
.notification {
display: flex;
flex-direction: row;
font-size: 12px;
padding: 8px;
min-height: 49px;
flex-grow: 1;
li {
list-style: none;
}
.details_container {
display: flex;
flex-direction: column;
flex-grow: 1;
margin-right: 8px;
.details {
display: flex;
color: #333;
align-items: center;
flex-grow: 1;
svg {
margin-right: 8px;
margin-left: 7px;
flex: 0 0 auto;
align-self: center;
flex-shrink: 0;
}
span {
flex-grow: 5;
text-align: left;
}
time {
flex: 0 0 auto;
margin-left: 8px;
padding-top: 2px;
color: #CCCCCC;
}
}
.additional_details {
flex-basis: 100%;
width: 226px;
margin-left: 11%;
span {
display: block;
word-break: break-all;
margin-left: 2px;
}
}
}
}
.expandable_container {
display: flex;
margin-top: 8px;
flex-direction: column;
border-bottom: 1px solid #CCCCCC;
.expandable {
align-items: center;
padding-top: 35px;
}
}
.expand {
display: flex;
align-items: center;
position: relative;
top: 10px;
border: 1px solid #CCCCCC;
width: 150px;
height: 20px;
left: 30%;
background-color: $white;
justify-content: center;
}
Could someone help me solve this thanks.

Resources