How to use CSS to modify the style like a design draft - css

I encountered a problem. I made a progress bar that will run to the corresponding position according to the value of progress. But I don't quite know how to modify the dot into a pattern like the design draft of the attached drawing, so that it can be wrapped in the progress-bar.
// 假設後端傳來的值是30
var progress = 10;
// 計算小圓點的位置
var dot = document.getElementById("dot");
var dotPosition = (progress / 30) * 100;
dot.style.left = dotPosition + "%";
body {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
#progress-bar-container {
width: 600px;
height: 5px;
background-color: #fff;
position: relative;
display: flex;
flex-wrap: nowrap;
}
.progress-bar {
width: 33.33%;
height: 5px;
background-color: #fff;
margin-right: 8px;
border-radius: 20px;
}
#progress-bar-1 {
background-color: #ddd;
}
#progress-bar-2 {
background-color: #ddd;
}
#progress-bar-3 {
background-color: #ddd;
margin-right: 0;
}
#dot {
width: 10px;
height: 10px;
border-radius: 50%;
background-color: orange;
position: absolute;
top: -3px;
left: 0;
transition: left 0.2s ease-out;
}
<div id="progress-bar-container">
<div class="progress-bar" id="progress-bar-1"></div>
<div class="progress-bar" id="progress-bar-2"></div>
<div class="progress-bar" id="progress-bar-3"></div>
<div id="dot"></div>
</div>

Related

CSS Add offset / distort between multiple borders?

Sandbox link: https://codesandbox.io/s/charming-hermann-pcpcsy?file=/src/styles.module.css
I want to create multi sector element using css. I need 4 segments as shown below:
<div className={classes.loader}>
<section className={classes.loader_sector}></section>
<section className={classes.loader_sector}></section>
<section className={classes.loader_sector}></section>
<section className={classes.loader_sector}></section>
</div>
and here's my CSS:
.loader_sector {
position: absolute;
width: 100%;
height: 100%;
border-radius: 50%;
border: 0.8rem solid transparent;
}
.loader_sector:nth-child(1) {
border-top-color: #fff;
}
.loader_sector:nth-child(2) {
border-left-color: #fff;
}
.loader_sector:nth-child(3) {
border-right-color: #fff;
}
.loader_sector:nth-child(4) {
border-bottom-color: #fff;
}
but this keeps all this circles stick together:
I want some gap at junction of every sector. Can someone help me achieve the same?
Edit one:
As suggested in comments using margin-top left and right solves the problem, but the core issue still remains, when I rotate them, they start contracting: https://codesandbox.io/s/charming-hermann-pcpcsy?file=/src/styles.module.css
Here you go, you can play with border radius and gap between sections to make it pretty.
.Spinner {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
background-color: purple;
display: flex;
align-items: center;
justify-content: center;
}
.loader > * {
box-sizing: border-box;
}
.loader {
color: red;
position: relative;
height: 10rem;
width: 10rem;
text-align: center;
vertical-align: center;
animation: rotate 2s ease-in-out infinite;
}
.loader_sector {
position: absolute;
width: 100%;
height: 100%;
border-radius: 50%;
border: 0.8rem solid transparent;
mix-blend-mode: overlay;
pointer-events: none;
}
.loader_sector:nth-child(1) {
border-top-color: pink;
margin-top: -5px;
}
.loader_sector:nth-child(2) {
border-left-color: blue;
margin-left: -5px;
}
.loader_sector:nth-child(3) {
border-right-color: green;
margin-left: 5px;
}
.loader_sector:nth-child(4) {
border-bottom-color: yellow;
margin-top: 5px;
}
#keyframes rotate {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
<div class=Spinner>
<div class=loader>
<section class=loader_sector></section>
<section class=loader_sector></section>
<section class=loader_sector></section>
<section class=loader_sector></section>
</div>
</div>
Replace this css code in your css file, it will work.
.Spinner {
position: absolute;
top: 0;
left: 0;
height: 100vh;
width: 100vw;
background-color: black;
display: flex;
align-items: center;
justify-content: center;
}
.loader > * {
box-sizing: border-box;
}
.loader {
/* background-color: white; */
position: relative;
height: 10rem;
width: 10rem;
border-radius: 50%;
}
.loader_sector {
position: absolute;
/* background-color: blue; */
position: absolute;
width: 100%;
height: 100%;
border-radius: 50%;
border: 0.8rem solid transparent;
}
.loader_sector:nth-child(1) {
border-top-color: pink;
margin-top: -10px;
}
.loader_sector:nth-child(2) {
border-left-color: blue;
margin-left: -10px;
}
.loader_sector:nth-child(3) {
border-right-color: green;
margin-left: 10px;
}
.loader_sector:nth-child(4) {
border-bottom-color: yellow;
margin-top: 10px;
}

Using multiple mix blend modes under a single parent

Just for fun I decided to make a progress bar element.. I also wanted to add a circular blob in the progress bar.
var modelList = [
'normal',
'multiply',
'screen',
'overlay',
'darken',
'lighten',
'color-dodge',
'color-burn',
'hard-light',
'soft-light',
'difference',
'exclusion',
'hue',
'saturation',
'color',
'luminosity'
]
let elem =
document.querySelector('.box');
let modelElem =
document.querySelector('.circle');
let progressBar =
document.querySelector('.progress');
let i = 0;
modelElem.innerHTML = modelList[i];
elem.onclick = function(){
if(i+1 < modelList.length) i++;
else i = 0;
progressBar.style.mixBlendMode= modelList[i];
modelElem.innerHTML = modelList[i];
}
* {
box-sizing: border-box;
}
.box {
display: flex;
align-items: center;
justify-content: center;
width: 100vw;
height: 100vh;
cursor: pointer;
1
}
.aaline {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
height: 40px;
width: 80%;
border: 8px solid black;
background: white;
z-index: 2;
}
.circle {
position: absolute;
height: 250px;
width: 250px;
border: 8px solid black;
border-radius: 50%;
background: white;
text-align: center;
font-size: 3rem;
z-index: 1;
}
.circle:first-of-type {
mix-blend-mode: lighten;
}
.progress {
position: absolute;
width: 20%;
height: 250px;
background: brown;
left: 0;
}
<div class="box">
<div class="aaline">
<div class="circle">
There.. There..
</div>
<div class="progress"></div>
</div>
<div class="circle"></div>
</div>
Adding mix blend mode to progress bar so that it blends in nicely with the aaline is the problem. I don't know why, but it is not blending.
Edit: toggling blends js

How to center object with CSS transform scale

I'm trying to implement a zoom in/out functionality, just like you would have on a document editor like google docs or any word processor application. The problem I'm having is that I cannot keep the "document" centered and also be able to scroll all of its parts into view. Here is a small demonstration of the problem: https://codepen.io/liviu_vasut/pen/dyGbwwO
document.getElementById('objectToScale').style.transform = "scale(3)";
.container {
display: flex;
align-items: center;
justify-content: center;
padding: 5px;
width: 300px;
height: 200px;
border: 1px solid #000000;
left: 0px;
top: 0px;
margin: 10px;
overflow: auto;
}
.object {
position: relative;
width: 120px;
height: 120px;
display: inline-block;
background-color: grey;
border-radius: 25px;
padding: 5px;
transform-origin: center;
transform: scale(1);
}
<div class="container">
<div id="objectToScale" class="object">x</div>
</div>
Thanks for your time.
You scale only some inner element inside the whole box, but expect see the whole box scaled. if you want to scale the white padding and all the inner content to stay visible (and be able to scroll to) you should add some wrapper inside with width: 100% and height: 100%, and scale it, so the whole content become scaled.
Also, as #HaoWu mentioned, you should set the transform-origin to 0 0.
The final product should look somewhat like this:
var scaled = false;
function toggleScale() {
var objects = document.getElementsByClassName('wrapper');
for (var i = 0; i < objects.length; i++) {
objects[i].style.transform = scaled ? 'scale(1)' : 'scale(3)';
}
scaled = !scaled;
}
.container {
width: 300px;
height: 200px;
border: 1px solid #000000;
left: 0px;
top: 0px;
margin: 10px;
overflow: auto;
}
.wrapper {
width: 100%;
height: 100%;
display: flex;
box-sizing: border-box;
align-items: center;
justify-content: center;
padding: 5px;
transform-origin: 0 0;
}
.object {
position: relative;
width: 120px;
height: 120px;
display: inline-block;
background-color: grey;
border-radius: 25px;
padding: 5px;
transform-origin: center;
transform: scale(1);
}
<input type="button" onclick="toggleScale()" value="Toggle Scale" />
<div class="container">
<div class="wrapper">
<div id="objectToScale" class="object">x</div>
</div>
</div>
Actually, use the transform-origin: 0 0; and manually set the scrollbar to the center:
var scaled = false;
function toggleScale() {
[...document.getElementsByClassName('object')].forEach(e => {
e.classList.toggle('scaled');
e.parentElement.scrollTop = (e.parentElement.scrollHeight - e.parentElement.clientHeight) / 2;
e.parentElement.scrollLeft = (e.parentElement.scrollWidth - e.parentElement.clientWidth) / 2;
});
}
* {
box-sizing: border-box;
}
.container {
display: flex;
align-items: center;
justify-content: center;
padding: 5px;
width: 300px;
height: 200px;
border: 1px solid #000000;
left: 0px;
top: 0px;
margin: 10px;
overflow: auto;
}
.object {
position: relative;
width: 120px;
height: 120px;
display: inline-block;
background-color: grey;
border-radius: 25px;
padding: 5px;
transform-origin: 0 0;
}
.scaled {
transform: scale(3);
}
<input type="button" onClick="toggleScale()" value="Toggle Scale" />
<div class="container">
<div class="object">cannot see the entire object when scaled</div>
</div>

Change background based on different hovered element

When hovering on each circle at the corner, background color in the main area should be changed so matches the color of the circle, and there is an adequate paragraph showing at the same time.
I have tried transition, opacity... but couldn't get it work.
Note, HTML has to be untouched.
* {
margin: 0;
padding: 0;
}
body {
position: relative;
height: 100vh;
text-align: center;
}
p {
font-family: Arial, Helvetica, sans-serif;
color: white;
}
.bg {
position: relative;
height: 100vh;
background-color: #333;
}
.circle {
height: 10px;
width: 10px;
border-radius: 50%;
border: white solid 2px;
z-index: 1;
}
.red.circle {
position: absolute;
top: 10%;
left: 10%;
background-color: red;
}
.green.circle {
position: absolute;
top: 10%;
right: 10%;
background-color: green;
}
.blue.circle {
position: absolute;
bottom: 10%;
left: 10%;
background-color: blue;
}
.orange.circle {
position: absolute;
bottom: 10%;
right: 10%;
background-color: orange;
}
p.red {
display: none;
background-color: red;
line-height: 100vh;
}
p.green {
display: none;
background-color: green;
line-height: 100vh;
}
p.blue {
display: none;
background-color: blue;
line-height: 100vh;
}
p.orange {
display: none;
background-color: orange;
line-height: 100vh;
}
<div class="red circle"></div>
<div class="green circle"></div>
<div class="blue circle"></div>
<div class="orange circle"></div>
<div class="bg">
<p class="red">Czerwony</p>
<p class="green">Zielony</p>
<p class="blue">Niebieski</p>
<p class="orange">Pomarańczowy</p>
</div>
Since they are somewhat in the same hierarchy, you can take advantage of the ~ general sibling selector which matches the second element only if it follows the first element (though not necessarily immediately):
/* added */
.red.circle:hover ~ .bg {
background-color: red;
}
.green.circle:hover ~ .bg {
background-color: green;
}
.blue.circle:hover ~ .bg {
background-color: blue;
}
.orange.circle:hover ~ .bg {
background-color: orange;
}
.red.circle:hover ~ .bg p.red { display: block; }
.green.circle:hover ~ .bg p.green { display: block; }
.blue.circle:hover ~ .bg p.blue { display: block; }
.orange.circle:hover ~ .bg p.orange { display: block; }
/* end of edit */
* {
margin: 0;
padding: 0;
}
body {
position: relative;
height: 100vh;
text-align: center;
}
p {
font-family: Arial, Helvetica, sans-serif;
color: white;
}
.bg {
position: relative;
height: 100vh;
background-color: #333;
transition: background-color 0.5s ease-in;
}
.circle {
height: 10px;
width: 10px;
border-radius: 50%;
border: white solid 2px;
z-index: 1;
}
.red.circle {
position: absolute;
top: 10%;
left: 10%;
background-color: red;
}
.green.circle {
position: absolute;
top: 10%;
right: 10%;
background-color: green;
}
.blue.circle {
position: absolute;
bottom: 10%;
left: 10%;
background-color: blue;
}
.orange.circle {
position: absolute;
bottom: 10%;
right: 10%;
background-color: orange;
}
p {
transition: background-color 1s ease-in;
}
p.red {
display: none;
background-color: red;
line-height: 100vh;
}
p.green {
display: none;
background-color: green;
line-height: 100vh;
}
p.blue {
display: none;
background-color: blue;
line-height: 100vh;
}
p.orange {
display: none;
background-color: orange;
line-height: 100vh;
}
<div class="red circle"></div>
<div class="green circle"></div>
<div class="blue circle"></div>
<div class="orange circle"></div>
<div class="bg">
<p class="red">Czerwony</p>
<p class="green">Zielony</p>
<p class="blue">Niebieski</p>
<p class="orange">Pomarańczowy</p>
</div>
You can add transition on the .bg class for the desired effect.
I would simplify your code to rely on pseudo element and data-attribute for background and content. It will be then easier to control as you don't need any complex selector:
body {
margin: 0;
background: #333;
min-height: 100vh;
}
.circle {
position: absolute;
height: 10px;
width: 10px;
border-radius: 50%;
border: white solid 2px;
}
.circle::before {
content: attr(data-text);
font-family: Arial, Helvetica, sans-serif;
text-align: center;
color: white;
line-height: 100vh;
font-size: 80px;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: -2;
background: inherit;
opacity: 0;
transition: 1s;
}
.circle:hover::before {
opacity: 1;
}
.circle.red {
top: 10%;
left: 10%;
background: red;
}
.circle.green {
top: 10%;
right: 10%;
background: green;
}
.circle.blue {
bottom: 10%;
left: 10%;
background: blue;
}
.circle.orange {
bottom: 10%;
right: 10%;
background: orange;
}
<div class="circle red" data-text="Czerwony"></div>
<div class="circle green" data-text="Zielony"></div>
<div class="circle blue" data-text="Niebieski"></div>
<div class="circle orange" data-text="Pomarańczowy"></div>
The css only solution of #soulshined is great, but just in case anyone wants to use javascript - here's a hint:
const bg = document.querySelector(".bg");
const circles = document.querySelectorAll(".circle");
circles.forEach(circle => circle.addEventListener("mouseenter", (e) => {
const style = getComputedStyle(e.target);
const backgroundColor = style.backgroundColor;
bg.style.backgroundColor = backgroundColor;
}))

css overlapping circle and text box

I am trying to produce this effect with CSS. I have tried creating a box with a triangle and then using negative margin to overlap it onto the circle, but cannot get it right.
Many thanks for any help.
fiddle
https://jsfiddle.net/Hastig/n3w0tztv/
Getting the circle to stay vertically centered and have the text container min-height the height of circle is tricky and is not worked out in this example. A cheap fix is adding align-items: center to .container at a breakpoint with #media.
body {
display: flex;
justify-content: center;
align-items: center;
margin: 0;
background-color: white;
height: 100vh;
}
.container {
display: flex;
width: 100%;
padding: 10px;
overflow: hidden;
}
.left {
position: relative;
display: flex;
width: 150px;
height: 150px;
margin-top: -4px;
margin-bottom: -4px;
margin-right: -17px;
background-color: #ec847c;;
border-style: solid;
border-color: white;
border-width: 4px;
border-radius: 100%;
z-index: 10;
}
.right {
position: relative;
display: flex;
flex: 2;
font-size: 20px;
color: white;
background-color: #4ca132;
}
.square {
position: absolute;
left: 0;
width: 50px;
height: 50px;
background-color: white;
overflow: hidden;
}
.square-top { top: 0; }
.square-btm { bottom: 0; }
.square::before {
content: "";
position: absolute;
display: flex;
width: 100%;
height: 100%;
transform: rotate(45deg) scale(2);
background-color: #4ca132;
z-index: 1;
}
.square-top::before { top: 50%; left: 50%; }
.square-btm::before { bottom: 50%; left: 50%; }
.text {
position: relative;
z-index: 2;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
padding: 20px 20px 20px 40px;
}
<div class="container">
<div class="left">
</div>
<div class="right">
<div class="square square-top"></div>
<div class="square square-btm"></div>
<div class="text">
Roles play an extremely important part in family funtion.
</div>
</div>
</div>

Resources