<div class="container">
<h1>
Binary Search Example
</h1>
<div class="description">
The number in the middle represents our current opacity guess.
</div>
<div class="range-container">
<div class="current-range"></div>
<div class="full-range"></div>
<div class="start-marker"></div>
<div class="end-marker"></div>
<div class="guess-marker"></div>
<div class="guess-number-container">
<div class="guess-number">0.50</div>
</div>
</div>
<div class="buttons">
<button id="guess_btn">Next Guess</button>
<button id="reset_btn">Reset</button>
</div>
<div class="banner">
<div class="overlay"></div>
<div class="banner-text">To begin, click the “next guess” button.</div>
</div>
<div class="disclaimer">
This demo is for illustrative purposes only, so it uses pretend numbers. In the real version, we would check our guesses against a target contrast. For the actual opacity checker, <a href="https://codepen.io/yaphi1/live/oNbEqGV">click here instead</a>.
</div>
</div>
body {
margin: 0px;
font-family: Montserrat, sans-serif;
color: #345;
}
h1 {
margin: 0px 0px 4px;
font-size: 30px;
}
.description {
margin-bottom: 16px;
}
.disclaimer {
margin-top: 20px;
font-size: 14px;
line-height: 1.4;
}
a {
color: #0098db;
font-weight: bold;
}
a:hover {
color: #c80;
}
.buttons {
display: flex;
justify-content: space-between;
}
button {
font-family: Montserrat, sans-serif;
padding: 10px 20px;
font-size: 16px;
font-weight: bold;
text-transform: uppercase;
cursor: pointer;
border-radius: 4px;
border: none;
background-color: #eee;
color: #456;
transition: all 0.2s;
}
button:hover {
color: #eee;
background-color: #333;
}
.container {
max-width: 800px;
padding: 20px;
margin: auto;
}
.range-container {
width: 100%;
height: 60px;
position: relative;
margin-bottom: 40px;
}
.full-range {
position: absolute;
left: 0px;
top: calc(50% - 2px);
width: 100%;
height: 4px;
background-color: #333;
}
.current-range {
height: 100%;
width: 100%;
background-color: #0098db;
position: absolute;
left: 0px;
top: 0px;
transform-origin: 0 0;
transition: all 0.5s;
}
.guess-marker {
width: 0px;
background-color: gold;
height: 100%;
position: absolute;
left: 50%;
top: 0px;
transition: all 0.2s;
}
.guess-marker::before {
content: "";
border: 2px solid gold;
position: absolute;
left: -2px;
top: -2px;
height: 100%;
width: 100%;
}
.guess-number-container {
position: absolute;
left: 50%;
top: calc(100% + 10px);
transition: all 0.2s;
}
.guess-number {
transform: translateX(-50%);
font-size: 20px;
}
.start-marker,
.end-marker {
width: 3px;
background-color: #333;
height: 100%;
position: absolute;
left: 0%;
top: 0px;
}
.end-marker {
left: auto;
right: 0%;
}
.start-marker::after,
.end-marker::after {
position: absolute;
top: calc(100% + 5px);
}
.start-marker::after {
content: "0";
left: 0px;
}
.end-marker::after {
content: "1";
right: 0px;
}
.banner {
margin-top: 20px;
background-color: #333;
color: #fff;
font-size: 20px;
text-align: center;
--overlay-opacity: 0.5;
background-image: url(https://assets.codepen.io/246719/valley-pexels-photo-414171.jpeg?width=567&height=290&format=auto);
background-size: cover;
position: relative;
height: 180px;
display: flex;
justify-content: center;
align-items: center;
}
.overlay {
position: absolute;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
background-color: #000;
opacity: 0.5;
transition: opacity 0.2s;
}
.banner-text {
position: relative;
padding: 20px;
max-width: 460px;
line-height: 1.4;
}
const reset_btn = document.getElementById("reset_btn");
const guess_btn = document.getElementById("guess_btn");
const range_bar = document.querySelector(".current-range");
const guess_marker = document.querySelector(".guess-marker");
const guess_number_container = document.querySelector(
".guess-number-container"
);
const guess_number = document.querySelector(".guess-number");
const overlay = document.querySelector(".overlay");
const banner_text = document.querySelector(".banner-text");
let guessInProgress = false;
guess_btn.addEventListener("click", makeGuess);
const guessRange = {
lowerBound: 0,
midpoint: 50,
upperBound: 100
};
const target = 33;
function makeGuess() {
if (guessInProgress) {
// console.log("in progress");
return;
}
guessInProgress = true;
let guess = guessRange.midpoint;
let opacity = (guess / 100).toFixed(2);
if (Math.round(guess) === target) {
banner_text.innerHTML = `We found our optimal opacity of ${opacity}!`;
guessInProgress = false;
return;
} else if (guess > target) {
banner_text.innerHTML = `Our opacity guess of ${opacity} was too large, so we eliminated it and everything ABOVE it.`;
guessRange.upperBound = guess;
} else if (guess < target) {
banner_text.innerHTML = `Our opacity guess of ${opacity} was too small, so we eliminated it and everything BELOW it.`;
guessRange.lowerBound = guess;
}
const rangeSize = guessRange.upperBound - guessRange.lowerBound;
guessRange.midpoint = rangeSize / 2 + guessRange.lowerBound;
range_bar.style.transform = `
translateX(${guessRange.lowerBound}%)
scaleX(${rangeSize}%)
`;
showGuess(guessRange.lowerBound, rangeSize);
// console.log(guessRange);
}
function reset() {
guessRange.lowerBound = 0;
guessRange.midpoint = 50;
guessRange.upperBound = 100;
showGuess(guessRange.lowerBound, 100);
banner_text.innerHTML = `Retry as many times as you'd like!`;
}
function showGuess(lowerBound, rangeSize) {
range_bar.style.transform = `
translateX(${lowerBound}%)
scaleX(${rangeSize}%)
`;
setTimeout(() => {
const opacity = (guessRange.midpoint / 100).toFixed(2);
guess_marker.style.left = guessRange.midpoint + "%";
guess_number_container.style.left = guessRange.midpoint + "%";
guess_number.innerHTML = opacity;
overlay.style.opacity = opacity;
setTimeout(() => {
guessInProgress = false;
}, 250);
}, 500);
}
reset_btn.addEventListener("click", reset);
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.