1. Advertising
    y u no do it?

    Advertising (learn more)

    Advertise virtually anything here, with CPM banner ads, CPM email ads and CPC contextual links. You can target relevant areas of the site and show ads based on geographical location of the user if you wish.

    Starts at just $1 per CPM or $0.10 per CPC.

create clock face with CSS

Discussion in 'CSS' started by iago111, Nov 17, 2020.

  1. #1
    Hallo,

    I would like to create a clock face with CSS.
    Right now I have a png for that. I would like to rebuild that with CSS. Does anybody have a hint how to start with that? (like with psuedo elements, position: absolute etc.) Here is the picture:

    [​IMG]

    Here is the CSS code that I have up to now.

    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    body {
      display: flex;
      justify-content: center;
      align-items: center;
      min-height: 100vh;
      background: #091921;
    }
    
    .clock {
      width: 350px;
      height: 350px;
      display: flex;
      justify-content: center;
      align-items: center;
      background: url(clock.png);
      background-size: cover;
      border: 4px solid #091921;
      border-radius: 50%;
    
      /* box-shadow */
      /* offset-x | offset-y | blur-radius | color */
    
      box-shadow: 0 -15px 15px rgba(255, 255, 255, 0.05),
        inset 0 -15px 15px rgba(255, 255, 255, 0.05), 0 15px 15px rgba(0, 0, 0, 0.3),
        inset 0 15px 15px rgba(0, 0, 0, 0.3);
    
    /* CSS for the hands */
    
    .clock:before {
    content: "";
    position: absolute;
    width: 15px;
    height: 15px;
    background: #fff;
    border-radius: 50%;
    z-index: 10000;
    }
    
    .clock .hour,
    .clock .min,
    .clock .sec {
    position: absolute;
    }
    
    .clock .hour,
    .hr {
    width: 160px;
    height: 160px;
    /* border: 3px solid #ff105e; */
    }
    
    .clock .min,
    .mn {
    width: 190px;
    height: 190px;
    /* border: 3px solid #eee2e6; */
    }
    
    .clock .sec,
    .sc {
    width: 230px;
    height: 230px;
    /* border: 3px solid #d7f336; */
    }
    
    .hr,
    .mn,
    .sc {
    display: flex;
    justify-content: center;
    position: absolute;
    /* align-items: center; */
    /* border: 3px solid #ff105e; */
    border-radius: 50%;
    }
    
    .hr:before {
    content: "";
    position: absolute;
    width: 8px;
    height: 80px;
    background: #ff105e;
    z-index: 10;
    border-radius: 6px 6px 0 0;
    }
    
    .mn:before {
    content: "";
    position: absolute;
    width: 4px;
    height: 90px;
    background: #fff;
    z-index: 11;
    border-radius: 6px 6px 0 0;
    }
    
    .sc:before {
    content: "";
    position: absolute;
    width: 2px;
    height: 150px;
    background: #fff;
    z-index: 12;
    border-radius: 6px 6px 0 0;
    }
    
    }
    Code (CSS):
    HTML:
    SEMrush
     <body>
        <div class="clock">
          <div class="hour">
            <div class="hr" id="hr"></div>
          </div>
          <div class="min">
            <div class="mn" id="mn"></div>
          </div>
          <div class="sec">
            <div class="sc" id="sc"></div>
          </div>
        </div>
    </body>
    HTML:
    Thanks a lot!
     
    Solved! View solution.
    iago111, Nov 17, 2020 IP
    SEMrush
  2. qwikad.com

    qwikad.com Illustrious Member Affiliate Manager

    Messages:
    6,534
    Likes Received:
    1,414
    Best Answers:
    25
    Trophy Points:
    425
    #2
    With javascript you can have a clock that shows the current time (on refresh):

    https://jsfiddle.net/1n8fxhvo/

    You can remove some elements if you just want the face.
     
    qwikad.com, Nov 17, 2020 IP
  3. iago111

    iago111 Greenhorn

    Messages:
    51
    Likes Received:
    4
    Best Answers:
    0
    Trophy Points:
    13
    #3
    Thanks a lor for this! I already have a JS solution that I can use, but I can compare the solutions. Does anybody have an idea how to do this with CSS? (I would like to do as much as possible with CSS)
     
    Last edited: Nov 19, 2020
    iago111, Nov 19, 2020 IP
  4. iago111

    iago111 Greenhorn

    Messages:
    51
    Likes Received:
    4
    Best Answers:
    0
    Trophy Points:
    13
    #4
    I stumbled over border: dashed in order to create these dashes in the circle but I think this is not very useful. Does anybody have experience with SVG? (stoke property in this case)?
     
    iago111, Nov 20, 2020 IP
  5. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,422
    Likes Received:
    1,892
    Best Answers:
    246
    Trophy Points:
    515
    #5
    Markup's a little heavy for my tastes, but this should get the job done.

    
    <div class="clockFace">
    	<div></div>
    	<span></span>
    	<span></span>
    <!-- .clockFace --></div>
    
    Code (markup):
    
    .clockFace {
    	position:relative;
    	width:10em;
    	height:10em;
    }
    
    .clockFace:before,
    .clockFace:after,
    .clockFace div:before,
    .clockFace div:after {
    	position:absolute;
    	width:1.5em;
    	line-height:1.5em;
    	text-align:center;
    }
    
    .clockFace:before,
    .clockFace:after {
    	left:50%;
    	margin-left:-0.75em;
    }
    
    .clockFace:before {
    	content:"12";
    	top:0;
    }
    
    .clockFace:after {
    	content:"6";
    	bottom:0;
    }
    
    .clockFace div:before,
    .clockFace div:after {
    	top:50%;
    	margin-top:-0.75em;
    }
    
    .clockFace div:before {
    	content:"9";
    	left:0;
    }
    
    .clockFace div:after {
    	content:"3";
    	right:0;
    }
    
    .clockFace span:after,
    .clockFace span:before {
    	content:"";
    	box-sizing:border-box;
    	position:absolute;
    	left:50%;
    	width:0.125em;
    	height:100%;
    	margin-left:-0.06125em;
    	border:solid #000;
    	border-width:1em 0;
    	transform:rotate(30deg);
    }
    
    .clockFace span:after {
    	transform:rotate(60deg);
    }
    
    .clockFace span + span:before {
    	transform:rotate(-30deg);
    }
    
    .clockFace span + span:after {
    	transform:rotate(-60deg);
    }
    
    Code (markup):
    That about what you want? Note, done in dynamic sizes since px is a giant middle finger to usability and accessibility.
     
    deathshadow, Nov 23, 2020 IP
  6. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,422
    Likes Received:
    1,892
    Best Answers:
    246
    Trophy Points:
    515
    #6
    Live demo here with working clock:

    https://cutcodedown.com/for_others/iago111/clock/

    You might find the clock code a bit simpler than most. Note that the hours are grabbed as 120ths of a day so they "tick" the 6 degrees the other elements do.
     
    deathshadow, Nov 23, 2020 IP
    malky66, kk5st and sarahk like this.
  7. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,422
    Likes Received:
    1,892
    Best Answers:
    246
    Trophy Points:
    515
    #7
    Update, I fixed a bug in the math, and made the 12th ticks smaller to match the original image more closely... so be sure to ctrl-f5 to get the latest version.

    Oh, and if you want to control the size, just change the font-size on .clockFace, it's fully scalable off that one value.

    Side note, I made it behave like a proper old-fashioned clock, where EVERY hand "ticks" to 60ths, not just the second hand. It's funny how "proper" analog clocks are actually digital in function.
     
    Last edited: Nov 24, 2020
    deathshadow, Nov 24, 2020 IP
  8. qwikad.com

    qwikad.com Illustrious Member Affiliate Manager

    Messages:
    6,534
    Likes Received:
    1,414
    Best Answers:
    25
    Trophy Points:
    425
    #8
    You need to get it out there. I've not seen ANY html/css based clocks till now.
     
    qwikad.com, Nov 24, 2020 IP
  9. iago111

    iago111 Greenhorn

    Messages:
    51
    Likes Received:
    4
    Best Answers:
    0
    Trophy Points:
    13
    #9
    #deathshadow, thanks a lot for that solution, it works quite well!

    My ideas was to build up some kind of reusable blueprints/templates/components.

    E.g. I have a clock face with numbers and strokes, so I can build a simple clock or a watch,
    then I can built a chronograph, a compass (adding 360 strokes e.g.), finally I can build a artificial horizon tool for a plane e.g.

    Therefore these components have to be simple and flexible at the same time.
    I recede from JS since I really do not want to use it for simple graphic elements. On the other hand I do not want to use
    pictures since I cannot modify them.
     
    iago111, Nov 24, 2020 IP
  10. #10
    Good idea. Made a medium article out of it.

    https://deathshadow.medium.com/html-css-analog-clock-with-minimal-javascript-9dcf9a16e079

    A more fleshed out version, with more text explaining the how/what/why of it. I switched up how the ticks and hands are drawn slightly, and by mistake found that border-radius does some 'funky' but attractive things to the hands.
     
    deathshadow, Nov 24, 2020 IP
  11. iago111

    iago111 Greenhorn

    Messages:
    51
    Likes Received:
    4
    Best Answers:
    0
    Trophy Points:
    13
    #11
    iago111, Nov 25, 2020 IP
  12. qwikad.com

    qwikad.com Illustrious Member Affiliate Manager

    Messages:
    6,534
    Likes Received:
    1,414
    Best Answers:
    25
    Trophy Points:
    425
    #12
    Unreal! What's truly unreal is how little amount of code it's taken.
     
    qwikad.com, Nov 25, 2020 IP
  13. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,422
    Likes Received:
    1,892
    Best Answers:
    246
    Trophy Points:
    515
    #13
    It's actually more code than the canvas version you linked to, it's just the code is in different spots, the CSS being the lion's share of it.

    With a little optimization that canvas version could be dropped down to just 1.82k of scripting, almost 1k less than the CSS approach if you add the CSS and JS together.

    
    (function(d) {
    
    	var
    		canvas = d.getElementById("canvas"),
    		ctx = canvas.getContext("2d"),
    		radius = canvas.height / 2;
    
    	ctx.translate(radius, radius);
    	radius *= 0.90;
    	drawClock();
    
    	function drawClock() {
    		drawFace();
    		drawNumbers();
    		drawTime();
    	}
    
    	function drawFace() {
    		var grad = ctx.createRadialGradient(0,0,radius*0.95, 0,0,radius*1.05);
    		grad.addColorStop(0, '#333');
    		grad.addColorStop(0.5, 'white');
    		grad.addColorStop(1, '#333');
    		ctx.beginPath();
    		ctx.arc(0, 0, radius, 0, 2 * Math.PI);
    		ctx.fillStyle = 'white';
    		ctx.fill();
    		ctx.strokeStyle = grad;
    		ctx.lineWidth = radius * 0.1;
    		ctx.stroke();
    		ctx.beginPath();
    		ctx.arc(0, 0, radius * 0.1, 0, 2 * Math.PI);
    		ctx.fillStyle = '#333';
    		ctx.fill();
    	}
    
    	function drawNumbers() {
    		ctx.font = radius * 0.15 + "px arial";
    		ctx.textBaseline = "middle";
    		ctx.textAlign ="center";
    		var
    			pos = radius * 0.85,
    			inc = Math.PI / 6,
    			ang = inc * 7;
    		for (var num = 1; num < 13; num++) {
    			ctx.save();
    			ctx.rotate(ang);
    			ctx.translate(0, pos);
    			ctx.rotate(-ang);
    			ctx.fillText(num.toString(), 0, 0);
    			ctx.restore();
    			ang += inc;
    		}
    	} // drawNumbers
    
    	function drawTime(){
    		var
    			sxd2Rad = Math.PI / 30,
    			now = new Date();
    		drawHand(
    			(now.getHours() * 5 + Math.floor(now.getMinutes() / 12)) * sxd2Rad,
    			0.5,
    			0.07
    		);
    		drawHand(
    			now.getMinutes() * sxd2Rad,
    			0.8,
    			0.07
    		);
    		drawHand(
    			now.getSeconds() * sxd2Rad,
    			0.9,
    			0.02
    		);
    	} // drawTime
    
    	function drawHand(pos, length, width) {
    		ctx.save();
    		ctx.beginPath();
    		ctx.lineWidth = width * radius;
    		ctx.lineCap = "round";
    		ctx.moveTo(0,0);
    		ctx.rotate(pos);
    		ctx.lineTo(0, -length * radius);
    		ctx.stroke();
    		ctx.restore();
    	} // drawHand
    
    	setInterval(drawClock, 1000);
    
    })(document);
    Code (markup):
    And that's with leveling the playing field by having it update on the second.

    Forked pen here:
    https://jsfiddle.net/Jason_Knight/1h0us4o7/26/

    The biggest optimizations there being moving calculations out of a loop, removal of unnecessary arguments creating stack overhead, and understanding radians killing off a few "variables for nothing".

    More than one way to fry a fish. The big issue is that if you want it dynamic size you need to hook onresize to recalc the size, or if you want EM that's a bit tricky to implement... and really we should ALL be working in EM for most everything since it's the only "true" accessible screen media measurement.
     
    Last edited: Nov 25, 2020
    deathshadow, Nov 25, 2020 IP