For my digital signage project I made a simple digital clock with date in JS. But when I align the clock on the right side of the top bar (which I need to do), the text shifts back and forth when the seconds update. This is due to the condensed font I am using (and I have to use it). Any ideas how to prevent that from happening?
Here's my code:
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
var y = today.getFullYear();
var o = today.getMonth();
var a = today.getDate();
var d = today.getDay();
var monthnames = new Array();
monthnames[0] = "January";
monthnames[1] = "February";
monthnames[2] = "March";
monthnames[3] = "April";
monthnames[4] = "May";
monthnames[5] = "June";
monthnames[6] = "July";
monthnames[7] = "August";
monthnames[8] = "September";
monthnames[9] = "Oktober";
monthnames[10] = "November";
monthnames[11] = "December";
var weekdays = new Array();
weekdays[0] = "Sunday";
weekdays[1] = "Monday";
weekdays[2] = "Tuesday";
weekdays[3] = "Wednesday";
weekdays[4] = "Thursday";
weekdays[5] = "Friday";
weekdays[6] = "Saturday";
m = checkTime(m);
s = checkTime(s);
a = checkTime(a);
document.getElementById('clock').innerHTML =
`<h1>${weekdays[d]}, ${a} ${monthnames[o]}, ${y}, <span id="clocktime">${h}:${m}:${s}</h1>`;
var t = setTimeout(startTime, 500);
}
function checkTime(i) {
if (i < 10) { i = "0" + i }; // Fügt vor einstelligen Zahlen (i > 10) eine Null hinzu
return i;
}
startTime()
@import url('https://fonts.googleapis.com/css?family=Ropa+Sans');
* {
font-family: Ropa Sans;
margin: 0;
}
.top-bar {
width: 100%;
height: 50px;
background-color: #ccc;
display: flex;
justify-content: flex-end;
}
.time {
margin-top: auto;
margin-bottom: auto;
margin-right: 1em;
}
<div class="top-bar">
<div class="time" id="clock"></div>
</div>
You can't use a variable-width font and right-align and not have the text move around. One of those two things (variable-width or right-alignment) has to give way (well, probably; you might just minimize one). :-)
You've said you have to use the variable-width font, so I have two workarounds (I think calling them "solutions" would be overkill :-) ):
Put the time at the beginning. This minimizes the effect; it only happens when the day changes.
Put the text left-aligned in a container that's at the maximum size you'll need, with the container right-aligned.
Make just the clock digits fixed-width and see if anyone complains. :-)
I didn't think of the third one until late, but #3 is probably your best bet.
Here's an example of #1:
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
var y = today.getFullYear();
var o = today.getMonth();
var a = today.getDate();
var d = today.getDay();
var monthnames = new Array();
monthnames[0] = "January";
monthnames[1] = "February";
monthnames[2] = "March";
monthnames[3] = "April";
monthnames[4] = "May";
monthnames[5] = "June";
monthnames[6] = "July";
monthnames[7] = "August";
monthnames[8] = "September";
monthnames[9] = "Oktober";
monthnames[10] = "November";
monthnames[11] = "December";
var weekdays = new Array();
weekdays[0] = "Sunday";
weekdays[1] = "Monday";
weekdays[2] = "Tuesday";
weekdays[3] = "Wednesday";
weekdays[4] = "Thursday";
weekdays[5] = "Friday";
weekdays[6] = "Saturday";
m = checkTime(m);
s = checkTime(s);
a = checkTime(a);
document.getElementById('clock').innerHTML =
`<h1><span id="clocktime">${h}:${m}:${s}</span> - ${weekdays[d]}, ${a} ${monthnames[o]}, ${y}</h1>`;
var t = setTimeout(startTime, 500);
}
function checkTime(i) {
if (i < 10) { i = "0" + i }; // Fügt vor einstelligen Zahlen (i > 10) eine Null hinzu
return i;
}
startTime()
@import url('https://fonts.googleapis.com/css?family=Ropa+Sans');
* {
font-family: Ropa Sans;
margin: 0;
}
.top-bar {
width: 100%;
height: 50px;
background-color: #ccc;
display: flex;
justify-content: flex-end;
}
.time {
margin-top: auto;
margin-bottom: auto;
margin-right: 1em;
}
<div class="top-bar">
<div class="time" id="clock"></div>
</div>
Here's #2, using a temporary-and-probably-rubbish value for the width; you'll want to do more diligence on the width to use:
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
var y = today.getFullYear();
var o = today.getMonth();
var a = today.getDate();
var d = today.getDay();
var monthnames = new Array();
monthnames[0] = "January";
monthnames[1] = "February";
monthnames[2] = "March";
monthnames[3] = "April";
monthnames[4] = "May";
monthnames[5] = "June";
monthnames[6] = "July";
monthnames[7] = "August";
monthnames[8] = "September";
monthnames[9] = "Oktober";
monthnames[10] = "November";
monthnames[11] = "December";
var weekdays = new Array();
weekdays[0] = "Sunday";
weekdays[1] = "Monday";
weekdays[2] = "Tuesday";
weekdays[3] = "Wednesday";
weekdays[4] = "Thursday";
weekdays[5] = "Friday";
weekdays[6] = "Saturday";
m = checkTime(m);
s = checkTime(s);
a = checkTime(a);
document.getElementById('clock').innerHTML =
`<h1>${weekdays[d]}, ${a} ${monthnames[o]}, ${y}, <span id="clocktime">${h}:${m}:${s}</span></h1>`;
var t = setTimeout(startTime, 500);
}
function checkTime(i) {
if (i < 10) { i = "0" + i }; // Fügt vor einstelligen Zahlen (i > 10) eine Null hinzu
return i;
}
startTime()
@import url('https://fonts.googleapis.com/css?family=Ropa+Sans');
* {
font-family: Ropa Sans;
margin: 0;
}
.top-bar {
width: 100%;
height: 50px;
background-color: #ccc;
display: flex;
justify-content: flex-end;
}
.time {
width: 450px;
margin-top: auto;
margin-bottom: auto;
margin-right: 1em;
}
<div class="top-bar">
<div class="time" id="clock"></div>
</div>
Here's #3. This time, the width isn't completely arbitrary, it's 1ch
, which is the width of the 0
in the current font (details):
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
var y = today.getFullYear();
var o = today.getMonth();
var a = today.getDate();
var d = today.getDay();
var monthnames = new Array();
monthnames[0] = "January";
monthnames[1] = "February";
monthnames[2] = "March";
monthnames[3] = "April";
monthnames[4] = "May";
monthnames[5] = "June";
monthnames[6] = "July";
monthnames[7] = "August";
monthnames[8] = "September";
monthnames[9] = "Oktober";
monthnames[10] = "November";
monthnames[11] = "December";
var weekdays = new Array();
weekdays[0] = "Sunday";
weekdays[1] = "Monday";
weekdays[2] = "Tuesday";
weekdays[3] = "Wednesday";
weekdays[4] = "Thursday";
weekdays[5] = "Friday";
weekdays[6] = "Saturday";
m = checkTime(m);
s = checkTime(s);
a = checkTime(a);
document.getElementById('clock').innerHTML =
`<h1>${weekdays[d]}, ${a} ${monthnames[o]}, ${y}, <span id="clocktime">${clockDigits(h)}${clockDigits(":")}${clockDigits(m)}${clockDigits(":")}${clockDigits(s)}</span></h1>`;
var t = setTimeout(startTime, 500);
}
function checkTime(i) {
if (i < 10) {
return "0" + i; // Fügt vor einstelligen Zahlen (i > 10) eine Null hinzu
}
return String(i);
}
function clockDigits(s) {
return String(s).split("").map(ch => `<span class="digit">${ch}</span>`).join("");
}
startTime()
@import url('https://fonts.googleapis.com/css?family=Ropa+Sans');
* {
font-family: Ropa Sans;
margin: 0;
}
.top-bar {
width: 100%;
height: 50px;
background-color: #ccc;
display: flex;
justify-content: flex-end;
}
.time {
margin-top: auto;
margin-bottom: auto;
margin-right: 1em;
}
#clocktime .digit {
display: inline-block;
width: 1ch;
text-align: center;
}
<div>x</div>
<div>x</div>
<div>x</div>
<div class="top-bar">
<div class="time" id="clock"></div>
</div>
(Note that in that third one I also made checkTime
reliably return a string instead of sometimes returning a string and other times return a number.)