Javascript - How to make a section 'active' when scrolled to - javascript

I'm very new to JavaScript so apologies if I'm lacking clarity in any of my description.
I've built a small website that has a java-script generated menu and I'm just wanting to add functionality to highlight a section (and make 'active') in the menu when scrolled to. I've put together the following, which isn't throwing any errors in the console, so I'm unsure what I've missed:
const sectionHead = document.querySelectorAll('h2');
const sections = document.querySelectorAll('section');
const nav = document.querySelector('nav');
// build the nav
function navMenu(){
for(let section of sectionHead){
let listItem = document.createElement("li");
listItem.innerHTML = section.textContent;
nav.appendChild(listItem);
listItem.classList.add('menu__link');
listItem.addEventListener("click", ()=>{
section.scrollIntoView({behavior: "smooth"});
});
};
}
navMenu();
const nav_items = document.querySelectorAll('.menu__link')
window.addEventListener("scroll", () => {
let current = "";
sections.forEach((section) => {
const sectionTop = section.offsetTop;
const sectionHeight = section.clientHeight;
if (pageYOffset >= sectionTop - sectionHeight / 3) {
current = section.getAttribute("id");
}
});
//set section as active
nav_items.forEach((li) => {
li.classList.remove("your-active-class");
section.classList.remove("your-active-class");
if (section.classList.contains(current)) {
section.classList.add("your-active-class");
//console.log (li.classList);
}
});
});
The 'your-active-class' class has some custom CSS setup so it will just change visibility in the menu.
Any help is really appreciated

This is how you would observe whether a DOM Element is within view, and apply/remove a classname to it. If you look at your inspector, you'll see the 'active' class being added/removed when they enter and exit view.
window.addEventListener("load", function() {
//Query objects on document load
const sections = document.querySelectorAll("section")
console.log(`We have ${sections.length} sections`)
// Create options for Observer:
const options = {
rootMargin: '100px 0px',
threshold: [0.25, 0, 0.25, 0]
}
// Create instance of IO:
let observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.intersectionRatio > 0) {
entry.target.classList.add('active')
} else {
entry.target.classList.remove('active')
}
})
}, options)
// Iterate over each queried el, and add observer:
sections.forEach(section => {
observer.observe(section)
})
})
section {
background-color: red;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 6rem auto;
transition: all 300ms ease-in-out;
}
.active {
background-color: rgba(0,255,0,0.3);
transition: all 300ms ease-in-out;
}
<section><div>This is the first section</div></section>
<section><div>This is the second</div></section>
<section><div>This is the third</div></section>

Related

Cannot implement shuffle bars feature in sorting algorithm visualizer - setTimeout updates are not rendering

I'm making a sorting algorithm visualizer project and I'm in the process of implementing a shuffle button. The visualization involves bars of different heights getting moved around. I would like the shuffle button to modify the bar array one step at a time, showcasing each swap at a high speed. I've tried tweaking many different things (some of which do move bars around in a strange manner), but I can't seem to get the desired functionality to work. Here's some of the relevant code:
// Swap does not modify the original array, but the implementation details don't really affect the result.
// It basically swaps two elements in the bar array, and then returns the updated array.
const swapBars = (bars, bar1, bar2) => {
if (!bars || !bar1 || !bar2) {
return;
}
const _bars = bars;
let _bar1 = bar1;
let _bar2 = bar2;
const tempLeft = _bar1.left;
_bar1.left = _bar2.left;
_bar2.left = tempLeft;
const temp = _bar1;
_bar1 = _bar2;
_bar2 = temp;
return _bars;
};
// Init bars is basically synchronous shuffle. It takes the array that is created and shuffles it
// because the array should begin in a shuffled state. This is working properly.
const initBars = (bars) => {
let currentIndex = bars.length - 1;
while (currentIndex > 0) {
// randomIndex will always be different from currentIndex, so each bar will always shuffle
const randomIndex = Math.floor(Math.random() * currentIndex);
swapBars(bars, bars[currentIndex], bars[randomIndex]);
currentIndex--;
}
setBarsToRender(bars);
};
// createBarArray is what is used to actually populate an empty array with bars depending on a number passed
// through by a slider. This is also working properly.
const createBarArray = (quantity) => {
let bars = [];
const width = calcWidthPercentage(quantity);
for (let i = 0; i < quantity; i++) {
const height = calcHeightPercentage(quantity, i + 1);
const left = calcLeftPosPercentage(quantity, i + 1);
bars.push({ correctPos: i, height: height, width: width, left: left });
}
return initBars(bars);
};
// shuffleBars seems to be broken. I've tried many different things, and this is just the latest snapshot of it.
// It is being called when the shuffle button is being clicked using `shuffleBars(barsToRender)` where barsToRender is the stateful value that is being rendered.
const shuffleBars = (bars) => {
let currentIndex = bars.length - 1;
while (currentIndex > 0) {
const randomIndex = Math.floor(Math.random() * currentIndex);
setTimeout(() => {
setBarsToRender((prev) => {
return swapBars(prev, prev[currentIndex], prev[randomIndex]);
});
}, 50 * (bars.length - currentIndex));
currentIndex--;
}
};
If I do something like moving the swapBars call inside setBarsToRender outside of it and then
do setBarsToRender[...bars], I can see some of the bars moving, but not with the intended behavior (the smallest bar is the only one that keeps swapping). I'm not sure if I'm misunderstanding how state updates work inside setTimeout, or if it's something else, so I'd greatly appreciate some help.
I removed the setTimeout and used a transition delay to create the staggered effect.
Working demo below:
const swapBars = (bars, bar1, bar2) => {
if (!bars || !bar1 || !bar2) {
return;
}
const _bars = bars;
let _bar1 = bar1;
let _bar2 = bar2;
const tempLeft = _bar1.left;
_bar1.left = _bar2.left;
_bar2.left = tempLeft;
const temp = _bar1;
_bar1 = _bar2;
_bar2 = temp;
return _bars;
};
const initBars = (bars) => {
let currentIndex = bars.length - 1;
while (currentIndex > 0) {
const randomIndex = Math.floor(Math.random() * currentIndex);
swapBars(bars, bars[currentIndex], bars[randomIndex]);
currentIndex--;
}
return bars;
};
const createBarArray = (quantity) => {
let bars = [];
const width = 100 / quantity;
for (let i = 0; i < quantity; i++) {
const height = width * (i + 1);
const left = width * i;
bars.push({ correctPos: i, height: height, width: width, left: left });
}
return initBars(bars);
};
function Bars({ quantity = 10 }) {
const [barsToRender, setBarsToRender] = React.useState([]);
React.useEffect(() => {
const bars = createBarArray(quantity);
setBarsToRender(bars);
}, [quantity]);
const shuffleBars = () => {
const bars = [...barsToRender];
setBarsToRender(initBars(bars));
};
return (
<div>
<ul
style={{
height: "50vh",
display: "flex",
position: "relative"
}}
>
{barsToRender.map((bar, i) => (
<Bar key={bar.correctPos} bar={bar} index={i} />
))}
</ul>
<button onClick={shuffleBars}>Shuffle</button>
</div>
);
}
function Bar({ bar, index: i }) {
return (
<li
style={{
background: "blue",
height: `${bar.height}%`,
width: `${bar.width}%`,
left: `${bar.left}%`,
position: "absolute",
bottom: 0,
transitionProperty: "left",
transitionTimingFunction: "ease-in-out",
transitionDuration: ".25s",
transitionDelay: `${i*50}ms`
}}
>
<p>{bar.correctPos}</p>
</li>
);
}
ReactDOM.createRoot(document.getElementById("root")).render(<Bars />)
p {
font-family: sans-serif;
font-weight: 700;
height: 1.5rem;
width: 1.5rem;
display: grid;
place-content: center;
background: white;
border-radius: 50%;
border: 1px solid;
}
ul {
padding: 0;
list-style-type: none;
}
li {
display: grid;
align-content: end;
justify-items: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
<div id="root"></div>

Several Intersection Observers tracking different elements merged into a single one

I have a simple code using the IntersectionObserver, that basically tells when an object is visible on the screen, when that happens I want a title to change to the same name of that visible element. The thing is that I've created 5 different variables for each observer related to each of the 5 upcoming areas. Is there a way to simplify this code?
Right now it works but seems to be wrong to me and I cannot figure out how to merge them all.
Thanks in advance!!
var observer = new IntersectionObserver(function(entries) {
if(entries[0].isIntersecting === true)
document.querySelector(".productTitle").innerHTML = "Logotype";
}, { threshold: [1] });
var observer1 = new IntersectionObserver(function(entries) {
if(entries[0].isIntersecting === true)
document.querySelector(".productTitle").innerHTML = "Branding";
}, { threshold: [1] });
var observer2 = new IntersectionObserver(function(entries) {
if(entries[0].isIntersecting === true)
document.querySelector(".productTitle").innerHTML = "Website Dev.";
}, { threshold: [1] });
var observer3 = new IntersectionObserver(function(entries) {
if(entries[0].isIntersecting === true)
document.querySelector(".productTitle").innerHTML = "3d Modeling";
}, { threshold: [1] });
var observer4 = new IntersectionObserver(function(entries) {
if(entries[0].isIntersecting === true)
document.querySelector(".productTitle").innerHTML = "Vectorial Work";
}, { threshold: [1] });
observer.observe(document.querySelector("#visibleLogo"));
observer1.observe(document.querySelector("#visibleBranding"));
observer2.observe(document.querySelector("#visibleWeb"));
observer3.observe(document.querySelector("#visible3d"));
observer4.observe(document.querySelector("#visibleVector"));
Assign a common class like .page to your articles Elements
You need only one IntersectionObserver instance, and you can attach it to all the desired .page inside a.forEach().
Use data-* attribute to store the desired title in the HTML itself like i.e: data-title="Title to show when in viewport"
const elTitle = document.querySelector(".productTitle");
const pageInViewport = (entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
elTitle.textContent = entry.target.dataset.title;
}
});
};
const pageObs = new IntersectionObserver(pageInViewport);
const obsOptions = {threshold: [1]};
// Attach observer to every .page element:
document.querySelectorAll('.page')
.forEach(EL => pageObs.observe(EL, obsOptions));
* {
margin: 0;
box-sizing: border-box;
}
.productTitle {
position: fixed;
top: 0;
background: gold;
}
.page {
padding: 30px;
border: 1px solid #000;
height: 100vh;
}
<div class="productTitle"></div>
<div class="page" id="visibleLogo" data-title="Logotype">visibleLogo</div>
<div class="page" id="visibleBranding" data-title="Branding">visibleBranding</div>
<div class="page" id="visibleWeb" data-title="Website Dev.">visibleWeb</div>
<div class="page" id="visible3d" data-title="3d Modeling">visible3d</div>
<div class="page" id="visibleVector" data-title="Vectorial Work">visibleVector</div>

React Portal input change removes elements

I've created this pen to demo it: https://codepen.io/no1melman/pen/WWyJqQ
essentially I have this portal:
const ChatArea = ({ children }) => {
const el = document.createElement("div");
el.classList.add('chatbox')
const root = document.getElementById("rootus");
useEffect(() => {
root.appendChild(el);
return () => root.removeChild(el);
}, []);
return createPortal(children, el);
};
And Use like:
const ChatBox = () => {
const [ reply, setReply ] = useState('');
const handleReply = (e) => {
e.preventDefault();
setReply(e.target.value);
}
return (
<ChatArea>
<div className="chat-title">Bot Convo</div>
<div className="chat-convo"></div>
<div className="chat-reply">
<input type="text" value={reply} onChange={handleReply} />
<button>Send</button>
</div>
</ChatArea>
)
}
For some reason as you start typing the body of the chatbox seems to disappear... I've put logs into the useEffect to see if that was causing it, but it didn't show what I thought
There are two issues here:
The first issue is
useEffect(() => {
root.appendChild(el);
return () => root.removeChild(el);
}, []);
Now as per the hooks principle the dependency should match the used variables inside the hook. If not used react will not run the effect next time.
SO in your case when you click on open chat it opens up the chat box. the effect ran and rendered the portal with the input box.
When you have typed the first letter and onChange happened
It triggered the rerender of ChatArea, which should have ideally run the effect again, but didn't run as dependency array is blank and react has not idea as to when re-render.so the effect ran once for the first time where chatArea ran UI mounted and next time, the effect did not run as dependency array is blank.
This line :
return createPortal(children, el); // is referring to the new el which is created
but not attached to DOM. Hence nothing is visible on UI inside chatbox.
Refer this link: do not miss dependencies React hooks FAQs sections they are great :)
2nd issue:
Ideally, new div should not be created every time. Persist the "div" element across consecutive rerenders
See this implementation: I know there can be other ways of implementing it.
Feedbacks are welcome.
const {
render,
createPortal
} = ReactDOM;
const {
useState,
useEffect,
useRef
} = React;
const ChatArea = ({
children
}) => {
const el = document.createElement("div");
el.classList.add('chatbox')
// This el above will be different in each render
// root will remain same, ideally root and chatdiv should be passed as props
const root = document.getElementById("rootus");
// this val and setVal is done to toggle render the chart area after
// chatDiv is updated
const [val, setVal] = useState(true)
const chatDiv = useRef(null)
// First useEffect to persist the div
useEffect(() => {
if (!chatDiv.current) {
chatDiv.current = el
setVal(!val)
}
}, [chatDiv])
useEffect(() => {
root.appendChild(chatDiv.current);
return () => {
return root.removeChild(chatDiv.current)
}; // you are removing it
}, [chatDiv, root]);
if (chatDiv.current) {
return createPortal(children, chatDiv.current)
}
return null
// In your case as the return happened first and found out the el
};
const ChatBox = () => {
const [reply, setReply] = useState('');
const handleReply = (e) => {
e.preventDefault();
setReply(e.target.value);
}
return ( <
ChatArea >
<
div className = "chat-title" > Bot Convo < /div>
<
div className = "chat-convo" > < /div>
<
div className = "chat-reply" >
<
input type = "text"
value = {
reply
}
onChange = {
handleReply
}
/> <
button > Send < /button> <
/div> <
/ChatArea>
)
}
const NavBar = ({}) => ( <
div className = "navbar" >
<
div > Home < /div> <
div > Somewhere < /div> <
/div>
);
const Main = () => {
const [showChat, setShowChat] = useState(false);
const openChat = () => {
setShowChat(true);
};
const chatterbox = showChat ? ( < ChatBox / > ) : null;
return ( <
div className = "container" >
<
h2 > Main < /h2> <
p >
It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.The point of
using Lorem Ipsum is that it has a more - or - less normal distribution of
letters, as opposed to using 'Content here, content here', making it look like readable English.Many desktop publishing packages and web page editors now use Lorem Ipsum as their
default model text, and a search
for 'lorem ipsum'
will uncover many web sites still in their infancy.Various versions have evolved over the years, sometimes by accident, sometimes on purpose(injected humour and the like). <
/p> <
p style = {
{
display: "flex",
justifyContent: "center"
}
} >
<
button onClick = {
openChat
} > Open Chat < /button> <
/p> <
p style = {
{
display: "flex",
flexDirection: "column",
justifyContent: "center",
backgroundColor: "red"
}
} >
{
chatterbox
} < /p> <
/div>
);
};
const App = ({}) => ( <
div className = "app" >
<
NavBar / >
<
Main / >
<
/div>
);
render( < App / > , document.getElementById("rootus"));
body {
font-family: Raleway;
}
* {
box-sizing: border-box;
}
#rootus {
position: relative;
height: 100vh;
display: flex;
justify-content: center;
}
.navbar {
display: flex;
justify-content: center;
}
.navbar>div {
padding: 10px;
}
.navbar>div:hover {
background-color: gray;
cursor: pointer;
}
.container {
width: 960px;
}
.app {
display: flex;
flex-direction: column;
align-items: center;
}
.chatbox {
width: 400px;
height: 200px;
position: absolute;
bottom: 0;
border: 2px solid black;
background: white;
display: flex;
flex-direction: column;
}
.chat-title {
background: black;
color: white;
}
.chat-convo {
flex: 1;
display: flex;
}
.chat-reply {
display: flex;
border-top: 1px solid black;
}
.chat-reply>input {
width: 80%;
padding: 8px;
border: none;
outline: none;
}
.chat-reply>button {
outline: none;
border: none;
flex: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
<div id="rootus">
</div>
Ui was not coming up proper in the stackoverflow code snippet, so I
had to edit somethings in styling. you can have a look at code pen
codepen linkaccording to your original styling

Reverse background-position animation without resetting

I created an animation with CSS that changes the background-position of an element over time, to create a sort of scrolling effect with the background.
#keyframes stars-animate {
0% {
background-position: 0 -500px;
}
100% {
background-position: 2000px -500px;
}
}
This works perfectly. However, I also want to start to rewind the animation and create a reverse scrolling event. This is triggered by some irrelevant action.
function triggerReverse(element) {
element.style.animationDirection = 'reverse';
}
However, when I set the animation-direction to reverse, it does work, but not before it flips the entire background.
Am I doing it wrong, or is that the wrong way to do it, and if so, what is the right way?
Edit: I need to be able to reverse the animation while it is playing
UPDATE
The renewed sample code below provide the effect that enables a user to interrupt/pause the animation (during the first iteration) and immediately start to reverse the animation.
Here it is using time to control. Record the elapsed time from the beginning of animation, and calculate how to start the reverse animation. There are 2 iterations defined in css to make a whole loop. Without user intervention, the animation pauses/stops after the first iteration. But if there is, pause the iteration and immediately re-start it with a calculated animation-delay time. This will looks like an immediate reverse, however actually it is a new start.
There is also a trick on how to re-start the animation. Please refer to the code comment.
I searched around but found nobody has mentioned a similar scenario so far, nor a similar solution. Instead of to use time to control, I would like to see other better approaches.
My test also proves that different running environments render slightly different smoothness. Fortunately, here in SO is the best.
Try the solution to see if it can works well in your own scenario.
const span = document.querySelector('span'),
button = document.querySelector('button'),
duration = 10; // animation-during
let startTime;
span.addEventListener('animationstart', () => {
startTime = Date.now();
button.style.visibility = 'visible';
});
span.addEventListener('animationiteration', () => span.style.animationPlayState = 'paused');
span.addEventListener('animationend', () => {
button.style.visibility = 'hidden';
});
button.addEventListener('click', () => {
span.classList.remove('my_anim');
void span.offsetWidth; // safely apply changes
span.classList.add('my_anim');
const elapsed = Date.now() - startTime;
const delay = (elapsed < duration * 1000) ? (elapsed / 1000 - duration * 2) : -duration;
span.style.animationDelay = `${delay}s`;
span.style.animationPlayState = 'running';
});
span.my_anim {
animation: 10s 2 alternate my_move;
}
#keyframes my_move {
from {
margin-left: 0;
}
to {
margin-left: 50%;
}
}
button {
visibility: hidden;
}
<div>
<span class="my_anim">#</span>
</div>
<button>reverse</button>
This example does not use background-position for animation but a plain character.
const span = document.querySelector("span"),
button = document.querySelector("button");
span.addEventListener(
"animationiteration",
function() {
this.classList.add("paused");
button.style.visibility = "visible";
}
);
button.addEventListener(
"click",
function() {
this.style.visibility = "hidden";
span.classList.remove("paused");
}
);
span {
animation: 3s 2 alternate my_move;
}
span.paused {
animation-play-state: paused;
}
#keyframes my_move {
from {
margin-left: 0;
}
to {
margin-left: 50%;
}
}
button {
visibility: hidden;
}
<div>
<span>#</span>
</div>
<button>reverse</button>
NB: Use -webkit- prefix for css animation when necessary.
building off of #themefield's answer above - thanks, #themefield! - this way works the 'best', not perfect. (Sometimes the letter isn't in exactly the right spot when it reverses.)
The approach that worked was
a) reset animation to forward / reverse at the end
b) replace the animation with its opposite on toggling, setting a - start time to try to position it where it was.
Often it works pretty good, sometimes a lot off.
span = document.querySelector('span')
button = document.querySelector('button')
timerElement = document.querySelector('#timerId')
duration = 3; // animation-during
let startTime = Date.now();
toSec = (msec) => msec / 1000
elapsedTimeMsec = () => Date.now() - startTime
elapsedTimeSec = () => toSec(elapsedTimeMsec())
updateTimer = () => timerElement.innerHTML = `${elapsedTimeSec().toPrecision(2)}s`
let intervalHandle;
startTimer = () => {
intervalHandle = window.setInterval(() => {
updateTimer()
}, 500)
}
endTimer = () => {
window.clearInterval(intervalHandle)
intervalHandle = null
}
span.addEventListener('animationstart', () => {
startTime = Date.now();
startTimer()
});
span.addEventListener('animationiteration', () => span.style.animationPlayState = 'paused');
toggleAnimation = (shouldDelay) => {
span.classList.remove('my_anim');
void span.offsetWidth;
span.classList.add('my_anim');
if(span.style.animationDirection !== 'reverse')
span.style.animationDirection = 'reverse';
else
span.style.animationDirection = 'normal';
if(shouldDelay !== null && shouldDelay) {
span.style.animationDelay = `-${elapsedTimeSec()}s`;
} else {
span.style.animationDelay = `0s`;
}
span.style.animationPlayState = 'running';
}
span.addEventListener('animationend', () => {
endTimer()
updateTimer()
toggleAnimation();
});
button.addEventListener('click', () => {
endTimer()
updateTimer()
toggleAnimation(true) // todo pass in delay!
});
span.my_anim {
font-size: 54px;
animation: 3s 1 normal both my_move;
}
#keyframes my_move {
from {
margin-left: 0;
}
to {
margin-left: 50%;
}
}
button {
/*visibility: hidden;*/
}
#timerId {
font-size: 24px;
color: darkturquoise;
position: fixed;
bottom: 0;
left: 50%;
}
<div>
<span class="my_anim">#</span>
</div>
<button>reverse</button>
<span id="timerId"></span>

How do I add class for time(clock)

I get date and clock.
var mydate = new Date();
var clock = tarih.getHours();
var minute = tarih.getMinutes();
And want this;
if (clock> 5) {
add this class, if have id "menu" = "menu_edit" (i dont know how can i do)
}
How can I do that?
If 'menu' is id of element:
document.querySelector('#menu').className += " menu_edit";
UPD:
According to your comment:
document.querySelector('.class1').className += ' class2';
Or if there are several elements:
var elems = document.querySelectorAll('.class1');
elems.forEach = [].forEach;
elems.forEach(function(el){
el.className += ' class2';
});
https://developer.mozilla.org/docs/Web/API/Document/querySelector - about function.
http://www.w3schools.com/cssref/css_selectors.asp - about selectors.
Maybe something like this. Please see the comments for an explanation.
checkout https://babeljs.io/ for info on compiling ES6 to ES5
const menu = document.querySelector('#menu')
const menuClasses = [
'menu--morning',
'menu--afternoon',
'menu--evening'
]
// helper function to toggle classes like a radio button
// this uses currying to lock in the classes and element, but
// allow us to change the active class dynamically
const toggleClasses = (classes, element) => clazz => {
element.classList.remove(...classes)
element.classList.add(clazz)
}
// create the toggle function and pass in the classes and the element
const toggleMenuClass = toggleClasses(menuClasses, menu)
// run a timer every n seconds
const timer = () => {
const date = new Date()
// I'm using seconds for the example as you will see the change
// but you should change this to hours
const second = date.getSeconds()
if (second < 20) {
toggleMenuClass('menu--morning')
}
else if (second < 40) {
toggleMenuClass('menu--afternoon')
}
else {
toggleMenuClass('menu--evening')
}
// just to show the current time for the example
menu.textContent = second
// call the timer function again after 500 milliseconds
setTimeout(timer, 500)
}
// init the timer on load
timer()
#menu {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
transition: 1s background;
font-size: 5em;
font-family: sans-serif;
color:#fff;
text-align: center;
line-height: 100vh;
}
#menu.menu--morning {
background: #AED6F1;
}
#menu.menu--afternoon {
background: #ABEBC6;
}
#menu.menu--evening {
background: #B95A75;
}
<div id="menu">clock</div>
Thanks everyone. I solved my problem with pHp.
Instead of adding class, i try take a different css page. Thanks for all things.
Have a nice day. :)
$clock = date('H');
if ($clock > 14) {
echo "<link rel='stylesheet' type='text/css' href='css/night.css'>";
}

Categories