I want to use these ripple buttons that I created, but when I do an <a href> tag the background color of the buttons change. I happen to believe it is in the CSS, but I cant be sure. I turned text decoration off so the underline so wouldn't show, but that's it about it.
var addRippleEffect = function(e) {
var target = e.target;
if (target.tagName.toLowerCase() !== 'button') return false;
var rect = target.getBoundingClientRect();
var ripple = target.querySelector('.ripple');
if (!ripple) {
ripple = document.createElement('span');
ripple.className = 'ripple';
ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px';
target.appendChild(ripple);
}
ripple.classList.remove('show');
var top = e.pageY - rect.top - ripple.offsetHeight / 2 - document.body.scrollTop;
var left = e.pageX - rect.left - ripple.offsetWidth / 2 - document.body.scrollLeft;
ripple.style.top = top + 'px';
ripple.style.left = left + 'px';
ripple.classList.add('show');
return false;
}
document.addEventListener('click', addRippleEffect, false);
body {
margin: 0;
padding: 0;
}
#wrap {
position: absolute;
width: 100%;
height: 100%;
display: flex;
flex-flow: column;
justify-content: center;
align-items: center;
}
h1 {
display: flex;
margin: 0;
padding: 0;
align-items: center;
flex: 2;
font-family: 'Open Sans';
}
#main {
flex: 5;
}
button {
position: relative;
display: block;
width: 13em;
height: 3em;
margin: 2em;
border: none;
outline: none;
letter-spacing: .2em;
font-weight: bold;
background: #dfdfdf;
cursor: pointer;
overflow: hidden;
user-select: none;
border-radius: 2px;
font-family: 'Open Sans';
}
button:nth-child(2) {
color: #fff;
background: #4285f4;
transition: all 0.3s ease-in-out;
}
button:nth-child(2):hover {
background: #6ea2f7;
}
button:nth-child(3) {
color: #fff;
background: #00bad2;
}
button:nth-child(4) {
color: #fff;
background: #ff8a80;
}
.ripple {
position: absolute;
background: rgba(0, 0, 0, .15);
border-radius: 100%;
transform: scale(0);
pointer-events: none;
}
.ripple.show {
animation: ripple .75s ease-out;
}
#keyframes ripple {
to {
transform: scale(2);
opacity: 0;
}
}
a {
text-decoration: none;
}
<link href='https://fonts.googleapis.com/css?family=Open+Sans:600' rel='stylesheet' type='text/css'>
<div id="wrap">
<h1>Ripple Effect</h1>
<div id="main">
<button>BUTTON</button>
<a href="http://www.google.com">
<button>BUTTON</button>
</a>
<button>BUTTON</button>
<button>BUTTON</button>
</div>
</div>
The reason it doesn't work is that button:nth-child(2) will match a button element which is the second child of its parent.
In your case, your button is not the 2nd child of its parent, because its parent is <a>.
Do this:
<button>
BUTTON
</button>
See how it works now?
For more information on nth-child vist the nth-child MDN page.
Related
Currently struggling to add the .is-active class to my header via javascript. If you add "is-active" to the header classes it works well. But I can't seem to work it out in javascript.
I just want the class to be added as soon as you start scrolling, and then removed when returning to the top.
Appreciate all the help!
HTML:
<header class="header">
<div class="header-nav flex container">
<figure class="header-logo">
<a href="#">
<img class="header-logo-light" src="images/logoWhite.png" alt="San Miguel Services Logo">
<img class="header-logo-dark" src="images/logoDark.png" alt="San Miguel Services Logo">
</a>
</figure>
<nav class="header-menu flex">
<div class="header-menu-li">
WELCOME
SERVICES
ABOUT
PORTFOLIO
CONTACT
</div>
</nav>
<div class="header-btn">
<button href="#" class="button header-btn">REQUEST A QUOTE</button>
</div>
</div>
</header>
CSS:
.header {
position: fixed;
z-index: 1;
width: 100vw;
line-height: 18px;
}
.header .header-logo-dark {
opacity: 0;
display: none;
}
.header .header-logo-light {
opacity: 1;
display: block;
}
.header.is-active .header-logo-dark {
opacity: 1;
display: block;
}
.header.is-active .header-logo-light {
opacity: 0;
display: none;
}
.header.is-active .header-menu-li a {
color: $darkBlue;
&::before {
background: linear-gradient(to right, $mediumGreen, $lightGreen);
}
}
.header.is-active .header-btn button {
background: $mediumGreen;
color: $white;
transition: 300ms ease-in-out;
&:hover {
box-shadow: inset 0 0 0 2px $darkBlue;
color: $darkBlue;
background: transparent;
}
}
.header.is-active {
background: $white;
}
.header-nav {
padding: 20px 5.5%;
position: relative;
justify-content: space-between;
margin: auto;
}
.header-logo {
position: relative;
a img {
height: 46px;
}
}
.header-menu {
align-items: center;
}
.header-menu-li {
a {
position: relative;
margin: 0 0.625rem;
font-weight: 500;
font-size: $font-sm;
color: $white;
transition: color 300ms ease-in-out;
&::before {
content: "";
display: block;
position: absolute;
height: 5px;
background: $white;
left: 0;
right: 0;
bottom: -33px;
opacity: 0;
transition: opacity 300ms ease-in-out;
}
&:hover {
opacity: 0.95;
&::before {
opacity: 1;
}
}
}
}
.header-btn {
height: 46px;
font-size: $font-sm;
font-weight: 500;
button {
background: transparent;
border: 1px solid $white;
transition: 200ms ease-in-out;
&:hover {
background: $white;
color: $darkBlue;
}
}
}
Try this code:
window.addEventListener("scroll", function(){
var header = document.querySelector(".header");
header.classList.toggle("is-active", window.scrollY > 0);
})
Try to use more semantic HTML, this will help you in building the site.
<div class="menu">
<ul>
<li>Home</li>
</ul>
</div>
<section id="home">
<div class="wrapper">
</div>
</section>
You can also add some initial CSS settings to help you build your site, like :root, * {}, etc...
If you still don't know what a :root is, look it up, this will make it a lot easier.
I left some example code.
/* GENERAL */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
list-style: none;
text-decoration: none;
}
:root {
font-size: 62.5%; /* 1rem = 10px */
}
html {
scroll-behavior: smooth;
}
html,
body {
width: 100%;
height: 100%;
}
body {
font-family: " ";
font-size: 1.6rem;
text-align: center;
overflow: overlay;
background-color: var(--name-var);
}
.wrapper {
width: min(50rem, 100%);
margin-inline: auto;
padding-inline: 2.4rem;
}
window.addEventListener('scroll', onScroll)
onScroll()
function onScroll() {
showNavOnScroll ();
showBackToTopButtonOnScroll();
activateMenuAtCurrentSection(home);
}
function activateMenuAtCurrentSection(section) {
const targetLine = scrollY + innerHeight / 2
// check if the section has passed the line
// what data will I need?
const sectionTop = section.offsetTop
const sectionHeight = section.offsetHeight
const sectionTopReachOrPassedTargetLine = targetLine >= sectionTop
// check if the base is below the target line
// what data will I need?
const sectionEndAst = sectionTop + sectionHeight
const sectionEndPassedTargetLine = sectionEndAst <= targetLine
console.log('Did the session bottom go over the line?', sectionEndPassedTargetLine)
// section boundaries
const sectionBoundaries =
sectionTopReachOrPassedTargetLine && !sectionEndPassedTargetLine
const sectionId = section.getAttribute('id')
const menuElement = document.querySelector(`.menu a[href*=${sectionId}]`)
menuElement.classList.remove('active')
if (sectionBoundaries) {
menuElement.classList.add('active')
}
}
// This is so that when you scroll down your navigation bar goes out
function showNavOnScroll() {
if (scrollY > 0) {
navigation.classList.add('scroll');
} else {
navigation.classList.remove('scroll');
}
}
// Will make them appear smooth
ScrollReveal({
origin:'top',
distance: '30px',
duration: 700,
}).reveal(`
#home`);
I am catching a click and according to click close the menu :
To catch the click the code I tried is :
function someFnc(e){
let currentTarget = menuContain.contains(e.target);
if(!currentTarget){
document.body.style.color = "red";
} else {
document.body.style.color = "blue";
}
}
Other code I tried is :
function someFnc(e){
if(e.target.contains(menuContain)){
document.body.style.color = "red";
} else {
document.body.style.color = "blue";
}
}
Both works the same can anyone tell the reason because I am using same function .contains.
One is checking click is inside menu or not and in other menu is catching click inside it or not
let menuToggleCheck = document.getElementById("menuTogglerCheckbox");
let menuFixBg = document.getElementById("menuFix");
let menu = document.getElementById("menuToggler");
menuToggleCheck.addEventListener('click', menuTogglerBackground)
function menuTogglerBackground() {
if (menuToggleCheck.checked) {
menuFixBg.style.backgroundColor = "rgba(126, 125, 125, 0.5)";
menuFixBg.style.width = "100vw";
menuFixBg.style.height = "100vh";
} else {
menuFixBg.style.backgroundColor = "transparent";
menuFixBg.style.width = "0vw"
menuFixBg.style.height = "0vh"
}
}
let menuContain = document.getElementById("menuContainer");
menuFixBg.addEventListener('click', function(e) {
let currentTarget = menuContain.contains(e.target);
// e.target.contains(menuContain)
if (!currentTarget) {
document.body.style.color = "red";
menuToggleCheck.checked = false;
menuTogglerBackground();
} else {
document.body.style.color = "blue";
}
})
* {
box-sizing: border-box;
}
body {
margin: 0px;
}
#menuFix {
position: fixed;
top: 0px;
}
#menuContainer {
width: 100px;
height: 100vh;
}
#menuToggler {
position: relative;
display: flex;
width: 90px;
height: 80px;
/* left: -100px; */
user-select: none;
}
#menuToggler input {
cursor: pointer;
position: absolute;
width: 40px;
height: 40px;
top: 7px;
left: 21px;
opacity: 0;
z-index: 2;
}
.menuBarCircle {
position: relative;
width: 40px;
height: 40px;
margin-top: 10px;
margin-left: auto;
margin-right: auto;
border: 1px solid black;
border-radius: 20px;
}
#menuToggler span {
position: relative;
display: block;
width: 26px;
height: 3px;
top: 10px;
left: 6px;
margin-bottom: 5px;
border-radius: 5px;
background: black;
transform-origin: 0px 0px;
transition: 0.2s;
z-index: 1;
}
#menuToggler span:nth-child(1) {
background: brown;
transform-origin: 0 0;
}
#menuToggler span:nth-child(3) {
background: brown;
transform-origin: 0 100%;
}
#menuToggler input:checked~.menuBarCircle span {
margin-left: 4px;
}
#menuToggler input:checked~.menuBarCircle span:nth-child(1) {
transform: rotate(45deg) translate(0px, -1px);
}
#menuToggler input:checked~.menuBarCircle span:nth-child(3) {
transform: rotate(-45deg) translate(0, 1px);
}
#menuToggler input:checked~.menuBarCircle span:nth-child(2) {
opacity: 0;
}
#menu {
position: absolute;
list-style-type: none;
width: 90px;
height: 100vh;
margin-top: auto;
padding: 50px 0;
background: white;
border-right: 1px solid black;
/* z-index: -1; */
transform: translate(-100%, 0);
transition: 0.5s width;
}
#menu a {
display: flex;
flex-flow: column;
text-decoration: none;
font-size: 14px;
width: 100%;
padding: 5px 10px;
margin: 5px 0;
color: black;
border: 2px solid white;
border-radius: 20px 0 0 20px;
}
#menu a li {
display: flex;
justify-content: center;
align-items: center;
}
#menu a:hover {
background: rgb(255, 155, 155);
border: 2px solid rgb(255, 155, 155);
}
#menuToggler input:checked~#menu {
display: block;
width: 180px;
transform: translate(0%, 0);
}
#menuToggler input:checked~#menu a {
display: flex;
flex-flow: row;
font-size: 18px;
}
<div id="menuFix">
<div id="menuContainer">
<div id="menuToggler">
<input type="checkbox" id="menuTogglerCheckbox" />
<div class="menuBarCircle">
<span></span>
<span></span>
<span></span>
</div>
<ul id="menu">
<a href="#">
<li>Home</li>
</a>
<a href="#">
<li>Settings</li>
</a>
<a href="#">
<li>About Us</li>
</a>
<a href="#">
<li>Help</li>
</a>
</ul>
</div>
</div>
</div>
<div>Hello World I am with you this is the grace of God to be with you</div>
Although both could have the same effect depending on the HTML structure, they both do not work the same.
And in your provided example, they both do not always have the same result.
firstNode.contains( secondNode ) checks to see if secondNode is a descendant of firstNode and returns this as a boolean value.
It will also return true if a node performs this check on itself; this firstNode.contains( firstNode ) will equate to true.
function someFnc(e){
let currentTarget = menuContain.contains(e.target);
if(!currentTarget){
document.body.style.color = "red";
} else {
document.body.style.color = "blue";
}
}
In the above example, currentTarget holds the answer to the question; "Is e.target a descendant of menuContain".
function someFnc(e){
if(e.target.contains(menuContain)){
document.body.style.color = "red";
} else {
document.body.style.color = "blue";
}
}
In this above code block, you check to see if menuContain is a descendant of e.target.
e.target being the node on which the event was dispatched, or in your code's case, the node that was clicked on.
You can find more information on what .contains() does on this page, and more information on what event.target is on this page.
As for why both appear to work the same on your current code ( but remember, they don't ), well...
let menuContain = document.getElementById("menuContainer");
menuFixBg.addEventListener('click', function(e) {
let currentTarget = menuContain.contains(e.target);
// e.target.contains(menuContain)
if (!currentTarget) {
document.body.style.color = "red";
menuToggleCheck.checked = false;
menuTogglerBackground();
} else {
document.body.style.color = "blue";
}
})
In the above code, in your current HTML structure, #menuContainer occupies all of #menuFix's space, so any click event dispatched from #menuFix will come from either #menuContainer or one of it's descendants.
Because e.target will always either be #menuContainer or one of it's descendants, let currentTarget = menuContain.contains(e.target); will always be true.
Meaning that the font color will turn to blue in any case, with the above code.
In the case of using if ( e.target.contains(menuContain) ) {, this will be different.
If the click event is dispatched from #menuContainer, the if statement will equate to true, but if it's dispatched from one of its descendants, it will equate to false.
This is because descendants of #menuContainer won't contain #menuContainer.
Meaning, depending on where you click, the font will either be red or blue. I would suggest trying out Inspect Element in a browser that supports it and hovering over #menuContainer and its descendants in the Elements list to see what element occupies what space as this will be highlighted on the page.
See the below snippet as an example of how if ( e.target.contains(menuContain) ) { will have differing results depending on where you click.
Clicking near the circle will dispatch a click event from #menuToggler or one of its descendants, meaning the if statement will equate to false and the text will be blue.
Clicking further down, away from the circle, will dispatch a click event from #menuContainer, meaning the if statement will equate to true and the text will be red.
let menuToggleCheck = document.getElementById("menuTogglerCheckbox");
let menuFixBg = document.getElementById("menuFix");
let menu = document.getElementById("menuToggler");
menuToggleCheck.addEventListener('click', menuTogglerBackground)
function menuTogglerBackground() {
if (menuToggleCheck.checked) {
menuFixBg.style.backgroundColor = "rgba(126, 125, 125, 0.5)";
menuFixBg.style.width = "100vw";
menuFixBg.style.height = "100vh";
} else {
menuFixBg.style.backgroundColor = "transparent";
menuFixBg.style.width = "0vw"
menuFixBg.style.height = "0vh"
}
}
let menuContain = document.getElementById("menuContainer");
menuFixBg.addEventListener('click', function(e) {
if ( e.target.contains(menuContain) ) {
// #menuContainer was a descendant of the Clicked Element
// Or the Clicked Element actually was #menuContainer
document.body.style.color = "red";
menuToggleCheck.checked = false;
menuTogglerBackground();
} else {
// #menuContainer was not a descendant of the Clicked Element
document.body.style.color = "blue";
}
})
* {
box-sizing: border-box;
}
body {
margin: 0px;
}
#menuFix {
position: fixed;
top: 0px;
}
#menuContainer {
width: 100px;
height: 100vh;
}
#menuToggler {
position: relative;
display: flex;
width: 90px;
height: 80px;
/* left: -100px; */
user-select: none;
}
#menuToggler input {
cursor: pointer;
position: absolute;
width: 40px;
height: 40px;
top: 7px;
left: 21px;
opacity: 0;
z-index: 2;
}
.menuBarCircle {
position: relative;
width: 40px;
height: 40px;
margin-top: 10px;
margin-left: auto;
margin-right: auto;
border: 1px solid black;
border-radius: 20px;
}
#menuToggler span {
position: relative;
display: block;
width: 26px;
height: 3px;
top: 10px;
left: 6px;
margin-bottom: 5px;
border-radius: 5px;
background: black;
transform-origin: 0px 0px;
transition: 0.2s;
z-index: 1;
}
#menuToggler span:nth-child(1) {
background: brown;
transform-origin: 0 0;
}
#menuToggler span:nth-child(3) {
background: brown;
transform-origin: 0 100%;
}
#menuToggler input:checked~.menuBarCircle span {
margin-left: 4px;
}
#menuToggler input:checked~.menuBarCircle span:nth-child(1) {
transform: rotate(45deg) translate(0px, -1px);
}
#menuToggler input:checked~.menuBarCircle span:nth-child(3) {
transform: rotate(-45deg) translate(0, 1px);
}
#menuToggler input:checked~.menuBarCircle span:nth-child(2) {
opacity: 0;
}
#menu {
position: absolute;
list-style-type: none;
width: 90px;
height: 100vh;
margin-top: auto;
padding: 50px 0;
background: white;
border-right: 1px solid black;
/* z-index: -1; */
transform: translate(-100%, 0);
transition: 0.5s width;
}
#menu a {
display: flex;
flex-flow: column;
text-decoration: none;
font-size: 14px;
width: 100%;
padding: 5px 10px;
margin: 5px 0;
color: black;
border: 2px solid white;
border-radius: 20px 0 0 20px;
}
#menu a li {
display: flex;
justify-content: center;
align-items: center;
}
#menu a:hover {
background: rgb(255, 155, 155);
border: 2px solid rgb(255, 155, 155);
}
#menuToggler input:checked~#menu {
display: block;
width: 180px;
transform: translate(0%, 0);
}
#menuToggler input:checked~#menu a {
display: flex;
flex-flow: row;
font-size: 18px;
}
<div id="menuFix">
<div id="menuContainer">
<div id="menuToggler">
<input type="checkbox" id="menuTogglerCheckbox" />
<div class="menuBarCircle">
<span></span>
<span></span>
<span></span>
</div>
<ul id="menu">
<a href="#">
<li>Home</li>
</a>
<a href="#">
<li>Settings</li>
</a>
<a href="#">
<li>About Us</li>
</a>
<a href="#">
<li>Help</li>
</a>
</ul>
</div>
</div>
</div>
<div>Hello World I am with you this is the grace of God to be with you</div>
As a reply to your comment, here is a snippet where the menu will close if the user clicks inside the menu.
And some additional comments.
let menuToggleCheck = document.getElementById("menuTogglerCheckbox");
let menuFixBg = document.getElementById("menuFix");
let menu = document.getElementById("menuToggler");
menuToggleCheck.addEventListener('click', menuTogglerBackground)
function menuTogglerBackground() {
if (menuToggleCheck.checked) {
menuFixBg.style.backgroundColor = "rgba(126, 125, 125, 0.5)";
menuFixBg.style.width = "100vw";
menuFixBg.style.height = "100vh";
} else {
menuFixBg.style.backgroundColor = "transparent";
menuFixBg.style.width = "0vw"
menuFixBg.style.height = "0vh"
}
}
let menuContain = document.getElementById("menuContainer");
menuFixBg.addEventListener('click', function(e) {
if ( e.target.id === "menuTogglerCheckbox" ) {
// The User clicked on the Menu Toggle Box, which will have opened or closed the menu already, so do nothing
return true;
}
// Check to see if the Click Target is inside the Menu Container
let currentTarget = menuContain.contains(e.target);
if ( currentTarget ) {
// The user clicked inside the Menu Container
document.body.style.color = "red";
// Close the menu
menuToggleCheck.checked = false;
menuTogglerBackground();
} else {
// The user clicked outside the Menu Container
document.body.style.color = "blue";
// Maybe also close the menu?
//menuToggleCheck.checked = false;
//menuTogglerBackground();
}
});
* {
box-sizing: border-box;
}
body {
margin: 0px;
}
#menuFix {
position: fixed;
top: 0px;
}
#menuContainer {
width: 100px;
height: 100vh;
}
#menuToggler {
position: relative;
display: flex;
width: 90px;
height: 80px;
/* left: -100px; */
user-select: none;
}
#menuToggler input {
cursor: pointer;
position: absolute;
width: 40px;
height: 40px;
top: 7px;
left: 21px;
opacity: 0;
z-index: 2;
}
.menuBarCircle {
position: relative;
width: 40px;
height: 40px;
margin-top: 10px;
margin-left: auto;
margin-right: auto;
border: 1px solid black;
border-radius: 20px;
}
#menuToggler span {
position: relative;
display: block;
width: 26px;
height: 3px;
top: 10px;
left: 6px;
margin-bottom: 5px;
border-radius: 5px;
background: black;
transform-origin: 0px 0px;
transition: 0.2s;
z-index: 1;
}
#menuToggler span:nth-child(1) {
background: brown;
transform-origin: 0 0;
}
#menuToggler span:nth-child(3) {
background: brown;
transform-origin: 0 100%;
}
#menuToggler input:checked~.menuBarCircle span {
margin-left: 4px;
}
#menuToggler input:checked~.menuBarCircle span:nth-child(1) {
transform: rotate(45deg) translate(0px, -1px);
}
#menuToggler input:checked~.menuBarCircle span:nth-child(3) {
transform: rotate(-45deg) translate(0, 1px);
}
#menuToggler input:checked~.menuBarCircle span:nth-child(2) {
opacity: 0;
}
#menu {
position: absolute;
list-style-type: none;
width: 90px;
height: 100vh;
margin-top: auto;
padding: 50px 0;
background: white;
border-right: 1px solid black;
/* z-index: -1; */
transform: translate(-100%, 0);
transition: 0.5s width;
}
#menu a {
display: flex;
flex-flow: column;
text-decoration: none;
font-size: 14px;
width: 100%;
padding: 5px 10px;
margin: 5px 0;
color: black;
border: 2px solid white;
border-radius: 20px 0 0 20px;
}
#menu a li {
display: flex;
justify-content: center;
align-items: center;
}
#menu a:hover {
background: rgb(255, 155, 155);
border: 2px solid rgb(255, 155, 155);
}
#menuToggler input:checked~#menu {
display: block;
width: 180px;
transform: translate(0%, 0);
}
#menuToggler input:checked~#menu a {
display: flex;
flex-flow: row;
font-size: 18px;
}
<div id="menuFix">
<div id="menuContainer">
<div id="menuToggler">
<input type="checkbox" id="menuTogglerCheckbox" />
<div class="menuBarCircle">
<span></span>
<span></span>
<span></span>
</div>
<ul id="menu">
<a href="#">
<li>Home</li>
</a>
<a href="#">
<li>Settings</li>
</a>
<a href="#">
<li>About Us</li>
</a>
<a href="#">
<li>Help</li>
</a>
</ul>
</div>
</div>
</div>
<div>Hello World I am with you this is the grace of God to be with you</div>
Is there a way I can hard code a number into the code instead of having "Goals completed: " and the progress bar still complete based on percentage? I do not want the users to see "Goals Completed" or have a input bar where they enter a number. I want to do all of that behind the scenes.
What I am really trying to do is get rid of the whole "Goals Completed: (input box)" prompt. So that I, for example, can just hard code: goals = 69 and then the progress circle reacts and shows 60% in the middle and 69 of 115 goals completed AND the green circle on the outside matches that. I do not want the user to be able to enter anywhere how many goals were completed or see a input prompt. I want to only be able to modify the number of goals completed behind the scenes in the JS code.
Here is my current code:
document.querySelector('.goals').addEventListener('change', function() {
var goals = parseInt(this.value);
var circle = document.querySelector('circle');
var percentdiv = document.querySelector('.percent');
var completed = document.querySelector('.completed');
completed.innerHTML = goals;
var totaldiv = document.querySelector('.total');
var total = totaldiv.innerHTML;
var pc = goals * 100 / total;
var r = circle.getAttribute('r').replace('%', '') * percentdiv.clientWidth / 100; //actual radius of the circle
var c = Math.PI * (r * 2); //circumference is 2*pi*r
if (isNaN(goals)) {
pc = 100;
} else if (pc < 0) {
pc = 0;
} else if (pc > 100) {
pc = 100;
}
document.querySelector('.number h2').innerHTML = Math.floor(pc) + '<span>%</span>';
var length = pc * c / 100;
circle.style.strokeDasharray = length + ' ' + (c - length);
circle.style.strokeWidth = (length > 0) ? '5%' : 0;
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#progress-bar {
position: absolute;
left: 50%;
top: 55%;
transform: translate(-51%, -50%);
width: 40%;
}
.container {
position: relative;
width: 100%;
display: flex;
justify-content: space-around;
}
.container .card {
position: relative;
width: 400px;
display: flex;
justify-content: center;
align-items: center;
height: 400px;
border-radius: 4px;
text-align: center;
overflow: hidden;
transition: 0.5s;
}
.container .card:before {
content: '';
position: absolute;
top: 0;
left: -50%;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.03);
pointer-events: none;
z-index: 1;
}
.percent {
position: relative;
width: 300px;
height: 300px;
border-radius: 50%;
border-color: transparent;
border-width: 0;
border-style: none;
rbox-shadow: inset 0 0 50px #000;
background-image: radial-gradient(#444 0%, #222 70%, transparent 70%, transparent 100%);
rbackground: #222;
z-index: 1000;
}
.percent .number {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
}
.percent .number h2 {
color: #777;
font-weight: 700;
font-size: 40px;
transition: 0.5s;
}
.card:hover .percent .number h2 {
color: #fff;
font-size: 60px;
}
.percent .number h2 span {
font-size: 24px;
color: #777;
transition: 0.5s;
}
.card:hover .percent .number h2 span {
color: #fff;
}
.text {
position: relative;
color: #777;
margin-top: 40px;
font-weight: 700;
font-size: 18px;
letter-spacing: 1px;
text-transform: uppercase;
transition: 0.5s;
}
svg {
width: 100%;
height: 100%;
z-index: 1000;
}
svg circle {
fill: none;
stroke-width: 0;
stroke-linecap: round;
stroke: #00ff43;
}
<div class="container">
<div class="card">
<div class="box">
<div class="percent">
<svg>
<circle cx="50%" cy="50%" r="47.5%"></circle>
</svg>
<div class="number">
<h2>0<span>%</span></h2>
</div>
</div>
<h2 class="text"><span class="completed">0</span> of <span class="total">115</span> Goals Completed</h2>
</div>
</div>
</div>
Goals completed: <input class="goals" type='number' />
Rather than having your logic for updating the circle stored in the event handler for the input, have it as a separate function which you can then call with any number, e.g. setGoals(50) would update the circle to say 50 of 115 goals completed and 43%.
You can then optionally include the input box to change the displayed value in the circle, or just call setGoals(<some number here>) anywhere in your code.
This gives you the code snippet:
function setGoals(goals) {
const circle = document.querySelector('circle');
const percentdiv = document.querySelector('.percent');
const completed = document.querySelector('.completed');
completed.innerHTML = goals;
const totaldiv = document.querySelector('.total');
const total = totaldiv.innerHTML;
let pc = goals * 100 / total;
const r = circle.getAttribute('r').replace('%', '') * percentdiv.clientWidth / 100; //actual radius of the circle
const c = Math.PI * (r * 2); //circumference is 2*pi*r
if (isNaN(goals)) {
pc = 100;
} else if (pc < 0) {
pc = 0;
} else if (pc > 100) {
pc = 100;
}
document.querySelector('.number h2').innerHTML = Math.floor(pc) + '<span>%</span>';
const length = pc * c / 100;
circle.style.strokeDasharray = length + ' ' + (c - length);
circle.style.strokeWidth = (length > 0) ? '5%' : 0;
}
// For testing purposes, set up the input box to edit the number of displayed goals
document.querySelector('.goals').addEventListener('change', (e) => {
const goals = parseInt(e.target.value);
setGoals(goals);
});
// On page load, manually set the goals to 50 for demonstration purposes
setGoals(50);
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#progress-bar {
position: absolute;
left: 50%;
top: 55%;
transform: translate(-51%, -50%);
width: 40%;
}
.container {
position: relative;
width: 100%;
display: flex;
justify-content: space-around;
}
.container .card {
position: relative;
width: 400px;
display: flex;
justify-content: center;
align-items: center;
height: 400px;
border-radius: 4px;
text-align: center;
overflow: hidden;
transition: 0.5s;
}
.container .card:before {
content: '';
position: absolute;
top: 0;
left: -50%;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.03);
pointer-events: none;
z-index: 1;
}
.percent {
position: relative;
width: 300px;
height: 300px;
border-radius: 50%;
border-color: transparent;
border-width: 0;
border-style: none;
rbox-shadow: inset 0 0 50px #000;
background-image: radial-gradient(#444 0%, #222 70%, transparent 70%, transparent 100%);
rbackground: #222;
z-index: 1000;
}
.percent .number {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
}
.percent .number h2 {
color: #777;
font-weight: 700;
font-size: 40px;
transition: 0.5s;
}
.card:hover .percent .number h2 {
color: #fff;
font-size: 60px;
}
.percent .number h2 span {
font-size: 24px;
color: #777;
transition: 0.5s;
}
.card:hover .percent .number h2 span {
color: #fff;
}
.text {
position: relative;
color: #777;
margin-top: 40px;
font-weight: 700;
font-size: 18px;
letter-spacing: 1px;
text-transform: uppercase;
transition: 0.5s;
}
svg {
width: 100%;
height: 100%;
z-index: 1000;
}
svg circle {
fill: none;
stroke-width: 0;
stroke-linecap: round;
stroke: #00ff43;
}
<div class="container">
<div class="card">
<div class="box">
<div class="percent">
<svg>
<circle cx="50%" cy="50%" r="47.5%"></circle>
</svg>
<div class="number">
<h2>0<span>%</span></h2>
</div>
</div>
<h2 class="text"><span class="completed">0</span> of <span class="total">115</span> Goals Completed</h2>
</div>
</div>
</div>
Goals completed: <input class="goals" type='number' />
...It's a little difficult to test here on Stack Overflow, but if you call setGoals(50) (or another number) then it'll update the displayed goals in the circle. I added the line setGoals(50) to the above code snippet as an example to show 50 goals on page load.
In my site, I have two divs within a container. One div has text in English and the other has text in mandarin I have a button on the side that I want the user to toggle and control the visibility of each div/language they are comfortable with. I'm using JS to add/remove class visibility (opacity and display). By default, I have the English one in view. My sketch works halfway, when a user clicks the button, the English div fades but the mandarin one doesn't appear. Code below-
HTML -
<div class="textSection">
<div class="eng about" id="eng">
<p>SHEK LEUNG
</p>
</div>
<div class="mandarin about" id="man">
<p>
「為Samson畢業後在倫敦創立的品牌
</p>
</div>
</div>
<button class="langChange">⥃</button>
css -
.textSection {
width: 50vw;
height: 80vh;
position: relative;
top: 10vh;
left: 30vw;
display: flex;
justify-content: center;
align-items: center;
}
.about {
position: absolute;
width: 100%;
height: 100%;
opacity: 1;
box-sizing: border-box;
transition: all 1s;
}
.eng {
border-radius: 10px;
background: url("72ppi/Asset\ 3.png");
background-size: 100% 100%;
font-family: Helvetica, sans-serif;
font-weight: bold;
font-size: 1.2rem;
line-height: 1.7;
text-align: justify;
text-transform: uppercase;
color: white;
padding: 3rem;
opacity: 1;
display: block;
}
.mandarin {
font-family: Hiragino Sans GB;
font-size: 1.3rem;
line-height: 2;
text-align: justify;
text-transform: uppercase;
font-weight: bold;
color: black;
padding: 3rem;
opacity: 1;
border-radius: 10px;
border: solid 2px black;
opacity: 0;
display: none;
}
.hidden {
display: none;
}
.visuallyhidden {
opacity: 0;
}
.seen {
display: block;
}
.visual {
opacity: 1;
}
.langChange {
position: absolute;
border: none;
padding: 1rem 2rem;
border-radius: 10px;
margin: 0;
text-decoration: none;
font-size: 2rem;
left: 20vw;
cursor: pointer;
background-color: transparent;
color: black;
}
JS -
let engBox = document.getElementById('eng'),
manBox = document.getElementById('man')
langbtn = document.querySelector('.langChange');
langbtn.addEventListener('click', function () {
console.log(engBox.classList);
if (engBox.classList.contains('hidden')) {
engBox.classList.remove('hidden');
setTimeout(function () {
engBox.classList.remove('visuallyhidden');
}, 20);
} else {
engBox.classList.add('visuallyhidden');
engBox.addEventListener('transitionend', function (e) {
engBox.classList.add('hidden');
}, {
capture: false,
once: true,
passive: false
});
}
}, false);
langbtn.addEventListener('click', function () {
console.log(manBox.classList);
if (manBox.classList.contains('seen')) {
manBox.classList.remove('seen');
setTimeout(function () {
manBox.classList.remove('visual');
}, 20);
} else {
manBox.classList.add('seen');
manBox.addEventListener('transitionend', function (e) {
manBox.classList.add('seen');
}, {
capture: false,
once: true,
passive: false
});
}
}, false);
Start simple and build up. Here is a minimal working visibility toggle. Position changes, layout, and most timing can be added to the CSS piece by piece until you have what you want.
const engBox = document.getElementById('eng');
const manBox = document.getElementById('man');
const langbtn = document.querySelector('.langChange');
langbtn.addEventListener('click', function () {
engBox.classList.toggle('transparent');
manBox.classList.toggle('transparent');
});
.about {
overflow: hidden;
transition: all 2s;
}
.transparent {
opacity: 0;
}
<div class="textSection">
<div class="eng about" id="eng">
<p>SHEK LEUNG
</p>
</div>
<div class="mandarin about transparent" id="man">
<p>
「為Samson畢業後在倫敦創立的品牌
</p>
</div>
</div>
<button class="langChange">⥃</button>
</div>
How do I get the text that says "this is just some placeholder text that should let you scroll" to be under the title? I thought seeing as there is a <br> tag after the title, the text would go under it?
(in case it's unclear in the snippet, the background image has an arrow pointing down, indicating that the user should scroll down upon arriving at the home page).
$(document ).ready(function(){
var counter = 0;
$('#menuIcon').click(function(){
counter+=1;
if (counter == 3){
}
});
});
var open = false;
function Drop(n) {
var i;
if (open == false) {
for (i = n; i < 5; i++) {
Drp(i)
}
open = true
} else if (open == true) {
for (i = n; i < 5; i++) {
Cls(i)
}
open = false
}
}
function Drp(n) {
var elem = document.getElementsByClassName("menu-con")[n];
var pos = -1 * window.innerHeight - n * 100;
var id = setInterval(frame, 5);
function frame() {
if (pos >= -10) {
clearInterval(id);
elem.style.top = 0 + 'px';
} else {
pos += 10;
elem.style.top = pos + 'px';
}
}
}
function Cls(n) {
var elems = document.getElementsByClassName("menu-con")[n];
var poss = 0;
var ids = setInterval(frames, 5);
function frames() {
if (poss <= -1 * window.innerHeight) {
clearInterval(ids);
elems.style.top = -1 * window.innerHeight + 'px';
} else {
poss += -7 - n * 2;
elems.style.top = poss + 'px';
}
}
}
* {
box-sizing: border-box;
max-width: 100%;
font-family: 'PT Sans Narrow', sans-serif;
font-weight: bold;
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
background-color: black;
background-image:url(foo.png);
background-repeat:no-repeat;
background-position: center;
background-size:cover;
background-attachment: fixed;
}
.menuBox {
display: none;
}
.menuBox a {
text-decoration: none;
color: black;
}
.menu-icon {
width: 50px;
height: 50px;
position: fixed;
top: 0;
right: 0;
margin: 10px 15px;
transform: scale(0.8);
padding: 0;
cursor: pointer;
z-index: 20
}
.menu-bar {
width: 50px;
height: 5px;
background: rgb(190, 190, 190);
position: absolute;
transition: all 0.3s;
font-weight: bold;
font-size: 50px
}
.menu-bar1 {
margin-top: 9px
}
.menu-bar2 {
margin-top: 23px
}
.menu-bar3 {
margin-top: 37px
}
.menu-icon.hover .menu-bar1 {
-webkit-transform: rotate(45deg) scaleX(0.7);
margin-top: 22px;
}
.menu-icon.hover .menu-bar2 {
opacity: 0
}
.menu-icon.hover .menu-bar3 {
-webkit-transform: rotate(-45deg) scaleX(0.7);
margin-top: 22px;
}
.menu {
width: 100%;
height: 100%;
display: -webkit-flex;
display: flex;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
}
.menu-con {
-webkit-flex-grow: 1;
flex-basis: 0;
flex-grow: 1;
display: -webkit-flex;
display: flex;
-webkit-justify-content: space-around;
position: relative;
top: -100%;
transition: all 0.5s
}
.menu-con a:before {
content: "";
display: block;
position: absolute;
top: 0;
left: 0;
z-index: 1;
width: 100%;
height: 100%;
opacity: 1;
background: rgba(0, 0, 0, 0);
-webkit-transition: all 0.5s;
transition: all 0.5s;
}
.menu-con:hover a:before {
background: rgba(0, 0, 0, 0.2)
}
.menu-con a {
height: 20px;
-webkit-align-self: center;
color: white;
font-size: 25px;
z-index: 2;
cursor: pointer
}
#media screen and (max-width: 600px) {
.menu-con {
min-width: 50%
}
}
#media screen and (max-width: 350px) {
.menu-con {
min-width: 100%
}
}
a {
text-decoration: none;
}
.title {
display:flex;
justify-content: center;
align-items:center;
font-size:50px;
color:white;
}
.homeText {
background-color:darkblue;
display:flex;
justify-content:center;
}
<html class="animated pulse">
<head>
<title>Ben Cohen</title>
<link href=style.css rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=PT+Sans+Narrow" rel="stylesheet">
<link href="animate.css" rel=stylesheet>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="main.js"></script>
<link rel=icon href=icon.png>
</head>
<body>
<div class="menu-icon" onclick="this.classList.toggle('hover');Drop(0)" id="menuIcon">
<div class="menu-bar menu-bar1"></div>
<div class="menu-bar menu-bar2"></div>
<div class="menu-bar menu-bar3"></div>
</div>
<div class="menu">
<div class="menu-con" style="background:red;" href="yayitworks.html">
HOME
</div>
<div class="menu-con" style="background:blue" id="hello">
<a>PORTFOLIO</a>
</div>
<div class="menu-con" style="background:darkorange;">
<a>POUS</a>
</div>
<div class="menu-con" style="background:green;">
<a>HOMEWORK</a>
</div>
<div class="menu-con" style="background:white;">
<a style="color:black">TEST PAGE</a>
</div>
</div>
<div class="homeText">
<div class="title">
THIS IS A TITLE.
</div><br>
<p>this is just some placeholder text that should let you scroll</p>
</div>
</body></html>
Remove display: flex; from your .hometext CSS.
.hometext {
background-color:darkblue;
justify-content:center;
}
You can also specify the flex direction:
.hometext {
background-color:darkblue;
justify-content:center;
display: flex;
flex-direction: column;
More info here...
https://www.w3schools.com/Css/css3_flexbox.asp
& here...
https://developer.mozilla.org/en-US/docs/Web/CSS/flex