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:

     <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
  2. qwikad.com

    qwikad.com Illustrious Member Affiliate Manager

    Messages:
    7,151
    Likes Received:
    1,656
    Best Answers:
    29
    Trophy Points:
    475
    #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 Member

    Messages:
    99
    Likes Received:
    4
    Best Answers:
    1
    Trophy Points:
    33
    #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 Member

    Messages:
    99
    Likes Received:
    4
    Best Answers:
    1
    Trophy Points:
    33
    #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,732
    Likes Received:
    1,998
    Best Answers:
    253
    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,732
    Likes Received:
    1,998
    Best Answers:
    253
    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,732
    Likes Received:
    1,998
    Best Answers:
    253
    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:
    7,151
    Likes Received:
    1,656
    Best Answers:
    29
    Trophy Points:
    475
    #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 Member

    Messages:
    99
    Likes Received:
    4
    Best Answers:
    1
    Trophy Points:
    33
    #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 Member

    Messages:
    99
    Likes Received:
    4
    Best Answers:
    1
    Trophy Points:
    33
    #11
    iago111, Nov 25, 2020 IP
  12. qwikad.com

    qwikad.com Illustrious Member Affiliate Manager

    Messages:
    7,151
    Likes Received:
    1,656
    Best Answers:
    29
    Trophy Points:
    475
    #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,732
    Likes Received:
    1,998
    Best Answers:
    253
    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
  14. iago111

    iago111 Member

    Messages:
    99
    Likes Received:
    4
    Best Answers:
    1
    Trophy Points:
    33
    #14
    O.k. guys, I implemented #deathshadow 's CSS tutorial:
    https://levelup.gitconnected.com/html-css-analog-clock-with-minimal-javascript-9dcf9a16e079

    My original idea behind all that was to create a stopwatch. Things getting more complicated now, when you have clockfaces withing the clockface.

    I started with the CSS, without JS- functionality: Here is a picture:
    chronograph.JPG
    https://drive.google.com/file/d/1_51gfHjMLH8KjUsv_AxBkgl3tY5SpGO-/view?usp=sharing

    The 3 small clockfaces represent the minutes (at 12), seconds (at 9) and 10-nth seconds (at 6). I used #deathshadow 's technique of drawing the tick-marks
    by drawing lines within the circle where the border of these lines are the tick-marks. Rotating them draws all the tick marks.
    That works perfectly fine for the main clock, however I get problems positioning these lines in the small clocks. I made it by try-and-error, what is always bad!

    There are also 2 further problems. For the seconds I need 15 containers. (15 * 2 :)before/:after) * 2 (rotation)) That should be refactored somehow. And concerning the 10nth seconds, I do not have tick marks on opposite sites: The numerical series is: [36,72,108,144,180,216,252,288,324,360].

    HTML:
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Deathshadow watch</title>
    
        <link rel="stylesheet" type="text/css" href="style.css" />
        <link rel="stylesheet" type="text/css" href="chrono.css" />
      </head>
      <body>
        <div id="clock-wrapper">
          <div id="clock">
            <span></span>
            <span></span>
            <span></span>
            <!-- <i></i>
            <i></i>
            <i></i> -->
          </div>
          <div id="chrono-min">
            <span></span>
            <span></span>
            <span></span>
          </div>
    
          <div id="chrono-tenth-sec"></div>
          <div id="chrono-sec">
            <span></span>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
          </div>
        </div>
    
    HTML:
    style.css:
    /
    * CLOCK WRAPPER */
    
    #clock-wrapper {
      font-size: 4em;
      position: relative;
      width: 10em;
      height: 10em;
      line-height: 1.5em;
      margin: 1em auto;
      padding: 0;
    }
    
    /* END OF CLOCK WRAPPER */
    
    #clock {
      position: relative;
      width: 10em;
      height: 10em;
      border: 0.0625em solid #444;
      border-radius: 50%;
      box-shadow: inset 0.125em 0.25em 0.5em #0005, -0.25em -0.5em 0.5em #fffc,
        0 0 0.0625em 0.5em #777, 0 0 0.0625em 0.5625em #000,
        0.125em 0.25em 0.5em 0.5em #0004;
    }
    
    #clock *,
    #clock *:before,
    #clock *:after {
      box-sizing: border-box;
    
    #clock span {
      position: absolute;
      top: 0;
      left: 4.9375em; /* 10/2 - width/2 */
      width: 0.125em;
      height: 100%;
    }
    
    #clock i,
    #clock span:before,
    #clock span:after {
      position: absolute;
      top: 0; /*  (10-height) / 2 */
      left: 0;
      width: 100%;
      height: 10em;
    }
    
    #clock span:nth-child(2) {
      transform: rotate(60deg);
    }
    
    #clock span:nth-child(3) {
      transform: rotate(120deg);
    }
    
    #clock span:before,
    #clock span:after {
      content: "";
      border-style: solid;
      border-color: #000;
      border-width: 0.5em 0;
      /* background-color: #0f0; */
    }
    
    #clock span:before {
      transform: rotate(0deg);
    }
    
    #clock span:after {
      transform: rotate(30deg);
    }
    
    
    
    Code (CSS):
    chrono.css

    /* stopwatch :before + :after */
    
    #chrono-min,
    #chrono-tenth-sec,
    #chrono-sec {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
      width: 3em;
      height: 3em;
    }
    
    #chrono-min {
      position: absolute;
      left: 3.5em; /* 10/2 - width/2 */
      top: 1em;
    }
    
    #chrono-sec {
      position: absolute;
      top: 3.5em;
      left: 1em;
    }
    
    #chrono-tenth-sec {
      position: absolute;
      left: 3.5em; /* 10/2 - width/2 */
      bottom: 1em;
    }
    
    #chrono-min:before {
      content: "";
      display: inline-block;
      width: 3em;
      height: 3em;
      -moz-border-radius: 50%;
      -webkit-border-radius: 50%;
      border-radius: 50%;
      background-color: #fff;
      border: 0.05em solid gray;
    }
    
    #chrono-tenth-sec:before {
      content: "";
      display: inline-block;
      width: 3em;
      height: 3em;
      -moz-border-radius: 50%;
      -webkit-border-radius: 50%;
      border-radius: 50%;
      background-color: #fff;
      border: 0.05em solid gray;
    }
    
    #chrono-sec:before {
      content: "";
      display: inline-block;
      width: 3em;
      height: 3em;
      -moz-border-radius: 50%;
      -webkit-border-radius: 50%;
      border-radius: 50%;
      background-color: #fff;
      border: 0.05em solid gray;
    }
    
    /* stopwatch MIN tick-marks */
    
    #chrono-min span {
      position: absolute;
      top: 0.05em;
      left: 1.55em; /* 3/2 - width/2 */
      width: 0.05em;
      height: 100%;
    }
    
    #chrono-sec span {
      position: absolute;
      top: 0.05em;
      left: 1.55em; /* 3/2 - width/2 */
      width: 0.02em;
      height: 100%;
    }
    
    #chrono-min i,
    #chrono-min span:before,
    #chrono-min span:after,
    #chrono-sec i,
    #chrono-sec span:before,
    #chrono-sec span:after {
      position: absolute;
      top: 0; /*  (3-height) / 2 */
      left: 0;
      width: 100%;
      height: 2.63em;
    }
    
    #chrono-min span:before,
    #chrono-min span:after,
    #chrono-sec span:before,
    #chrono-sec span:after {
      content: "";
      border-style: solid;
      border-color: #000;
      border-width: 0.2em 0;
      /* background-color: #0f0; */
    }
    
    /* ROTATE MIN */
    
    #chrono-min span:before {
      transform: rotate(0deg);
    }
    
    #chrono-min span:after {
      transform: rotate(30deg);
    }
    
    #chrono-min span:nth-child(2) {
      transform: rotate(60deg);
    }
    
    #chrono-min span:nth-child(3) {
      transform: rotate(120deg);
    }
    
    /* ROTATE SEC */
    
    #chrono-sec span:before {
      transform: rotate(0deg);
    }
    
    #chrono-sec span:before {
      transform: rotate(6deg);
    }
    
    #chrono-sec span:nth-child(2) {
      transform: rotate(12deg);
    }
    
    #chrono-sec span:nth-child(3) {
      transform: rotate(24deg);
    }
    
    #chrono-sec span:nth-child(4) {
      transform: rotate(36deg);
    }
    
    #chrono-sec span:nth-child(5) {
      transform: rotate(48deg);
    }
    
    #chrono-sec span:nth-child(6) {
      transform: rotate(60deg);
    }
    
    #chrono-sec span:nth-child(7) {
      transform: rotate(72deg);
    }
    
    #chrono-sec span:nth-child(8) {
      transform: rotate(84deg);
    }
    
    #chrono-sec span:nth-child(9) {
      transform: rotate(96deg);
    }
    
    #chrono-sec span:nth-child(10) {
      transform: rotate(108deg);
    }
    
    #chrono-sec span:nth-child(11) {
      transform: rotate(120deg);
    }
    
    #chrono-sec span:nth-child(12) {
      transform: rotate(132deg);
    }
    
    #chrono-sec span:nth-child(13) {
      transform: rotate(144deg);
    }
    
    #chrono-sec span:nth-child(14) {
      transform: rotate(156deg);
    }
    
    #chrono-sec span:nth-child(15) {
      transform: rotate(168deg);
    }
    
    Code (CSS):
     
    iago111, Dec 30, 2020 IP
  15. iago111

    iago111 Member

    Messages:
    99
    Likes Received:
    4
    Best Answers:
    1
    Trophy Points:
    33
    #15
    Any suggestions?
     
    iago111, Jan 7, 2021 IP