This commit is contained in:
Rasmus Andersson 2018-02-21 12:20:04 -08:00
parent bd425b8fb8
commit 2e929794e7
6 changed files with 299 additions and 41 deletions

View file

@ -60,6 +60,7 @@ endfor
<meta property="og:locale" content="en_US" /> <meta property="og:locale" content="en_US" />
</head> </head>
<body> <body>
<div id="hud-notification"><div class="msg">Hello</div></div>
<script src="{{url_root}}res/base.js?v={{ base_js_v }}"></script> <script src="{{url_root}}res/base.js?v={{ base_js_v }}"></script>
<div class="row menu"> <div class="row menu">

View file

@ -39,16 +39,16 @@ endfor
<formula> <formula>
tracking = tracking =
<const>a</const> + <const>b</const> × <const>a</const> + <const>b</const> ×
<const>e</const><sup>(<const>c</const> × fontSize)</sup> <const title="Base of natural logarithm; ≈2.718">e</const><sup>(<const>c</const> × <const>z</const>)</sup>
</formula> </formula>
<formula> <formula>
leading = <num>1.4</num> × fontSize leading = round(<num data-binding="var-l">1.4</num> × <const>z</const>)
</formula> </formula>
<formula title="Values for Inter UI"> <formula title="Values for Inter UI">
<g><const title="Constant a">a</const> = <num data-binding="var-a">-0.016</num></g> &nbsp;&nbsp; <g><const title="Constant a">a</const> = <num data-binding="var-a">-0.016</num></g> &nbsp;&nbsp;
<g><const title="Constant b">b</const> = <num data-binding="var-b">0.21</num></g> &nbsp;&nbsp; <g><const title="Constant b">b</const> = <num data-binding="var-b">0.21</num></g> &nbsp;&nbsp;
<g><const title="Constant c">c</const> = <num data-binding="var-c">-0.18</num></g> &nbsp;&nbsp; <g><const title="Constant c">c</const> = <num data-binding="var-c">-0.18</num></g> &nbsp;&nbsp;
<g class="wide-window"><const title="Base of natural logarithm">e</const><num>2.718</num></g> <g><const>z</const> = font size</g>
</formula> </formula>
</p> </p>
<p class="wide-window"> <p class="wide-window">
@ -251,10 +251,10 @@ var a = -0.016, b = 0.21, c = -0.18; // di=0.000532 on set-2018-02-20
var l = 1.4 var l = 1.4
// InterUIDynamicTracking takes the font size in points or pixels and returns // _InterUIDynamicTracking is a version of InterUIDynamicTracking that
// the compensating tracking in EM. // uses some global variables that are adjustable.
// //
function InterUIDynamicTracking(fontSize, weightClass) { function _InterUIDynamicTracking(fontSize, weightClass) {
// Note: weightClass is currently unused // Note: weightClass is currently unused
// //
// y = -0.01021241 + 0.3720623 * e ^ (-0.2808687 * x) // y = -0.01021241 + 0.3720623 * e ^ (-0.2808687 * x)
@ -263,7 +263,7 @@ function InterUIDynamicTracking(fontSize, weightClass) {
// //
return a + b * Math.pow(Math.E, c * fontSize) return a + b * Math.pow(Math.E, c * fontSize)
// [6 - 38] 0.05798 .. -0.01099 (midpoint = 12.533) // [6 - 38] 0.05798 .. -0.01099 (midpoint = 12.533)
//
// y = 0.025 - (ln(x) * 0.01) // y = 0.025 - (ln(x) * 0.01)
// return 0.025 - Math.log(fontSize) * 0.01 // return 0.025 - Math.log(fontSize) * 0.01
} }
@ -322,7 +322,7 @@ Sample.prototype.idealDistance = function(fontSize) {
Sample.prototype.setFontSize = function(fontSize) { Sample.prototype.setFontSize = function(fontSize) {
this.fontSize = fontSize this.fontSize = fontSize
this.tracking = baseTracking + InterUIDynamicTracking(fontSize, weightClass) this.tracking = baseTracking + _InterUIDynamicTracking(fontSize, weightClass)
this.lineHeight = InterUIDynamicLineHeight(fontSize, weightClass) this.lineHeight = InterUIDynamicLineHeight(fontSize, weightClass)
this.maxBoxWidth = Math.round(fontSize * (this.tracking + 1) * 25) this.maxBoxWidth = Math.round(fontSize * (this.tracking + 1) * 25)
@ -352,11 +352,11 @@ Sample.prototype.setFontSize = function(fontSize) {
} }
Sample.prototype.cssProperties = function() { Sample.prototype.cssProperties = function() {
return { return [
fontSize: round(this.fontSize, 3) + 'px', ['font-size', round(this.fontSize, 3) + 'px'],
letterSpacing: round(this.tracking, 3) + 'em', ['letter-spacing', round(this.tracking, 3) + 'em'],
lineHeight: round(this.lineHeight, 3) + 'px', ['line-height', round(this.lineHeight, 3) + 'px'],
} ]
} }
Sample.prototype.render = function() { Sample.prototype.render = function() {
@ -479,7 +479,7 @@ function updateGraphPlot() {
graph.clear() graph.clear()
graph.plotLine(idealValuesList, '#0d3') graph.plotLine(idealValuesList, '#0d3')
graph.plotf(function(x) { graph.plotf(function(x) {
return InterUIDynamicTracking(x, weightClass) return _InterUIDynamicTracking(x, weightClass)
}) })
if (focusedSample) { if (focusedSample) {
var graphedFontSize = Math.min(24, focusedSample.fontSize) // clamp to [-inf,24] var graphedFontSize = Math.min(24, focusedSample.fontSize) // clamp to [-inf,24]
@ -496,13 +496,22 @@ codeOutput.addEventListener('focus', function(ev) {
codeOutput.select() codeOutput.select()
}, {passive:false,capture:true}) }, {passive:false,capture:true})
codeOutput.addEventListener('pointerdown', function(ev) {
// TODO: don't do this if codeOutput is focused
ev.preventDefault()
ev.stopPropagation()
codeOutput.select()
document.execCommand("copy")
HUDNotification.show('Copied to clipboard')
}, {passive:false,capture:true})
function updateCodeView() { function updateCodeView() {
var s = '' var s = ''
if (focusedSample) { if (focusedSample) {
var cssprops = focusedSample.cssProperties() var props = focusedSample.cssProperties()
var props = Object.keys(cssprops)
props.forEach(function(prop, i) { props.forEach(function(prop, i) {
s += prop + ': ' + cssprops[prop] + ';' var name = prop[0], value = prop[1]
s += name + ': ' + value + ';'
if (i != props.length-1) { if (i != props.length-1) {
s += '\n' s += '\n'
} }

61
docs/index.css Normal file
View file

@ -0,0 +1,61 @@
#hidden-text-input {
position: absolute;
left:0;
top:0;
background: none;
border: none;
opacity: 0;
pointer-events: none;
}
.dynmet-calc {
font-size: 18px;
line-height: 26px;
user-select: text;
}
.dynmet-calc input {
border: none;
box-shadow: inset 0 -1px 0 0 rgba(255, 255, 255, 0.3);
background: transparent;
font: inherit;
color: inherit;
outline: none;
margin: 0 0.2em;
width: 40px;
text-align: center;
line-height: inherit;
color: #eee;
user-select: text;
}
.dynmet-calc input:focus {
color: #fff;
box-shadow: inset 0 -2px 0 0 rgb(43, 139, 247);
}
.dynmet-calc input[type=number]::-webkit-inner-spin-button,
.dynmet-calc input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
.dynmet-calc .arrow {
margin: 0 0.8em;
color: #eee;
}
.dynmet-calc #dynmet-tracking {
box-shadow: none;
width: 57px;
margin-right: 0.1em;
color: #eee;
}
.dynmet-calc #dynmet-tracking.percent {
width: 34px;
}
.dynmet-calc #dynmet-unit:hover {
color: rgb(43, 139, 247);
}
.dynmet-calc #dynmet-unit:active {
color: white;
}

View file

@ -1,6 +1,23 @@
--- ---
layout: default layout: default
--- ---
{%
capture url_root
%}{% if site.safe == false %}/{% else %}/inter/{% endif
%}{%
endcapture %}{%
for file in site.static_files %}{%
assign _path = file.path | remove_first: "/inter" %}{%
if _path == "/index.css" %}{%
assign index_css_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
endif %}{%
endfor
%}
<link rel="stylesheet" href="index.css?v={{ index_css_v }}">
<input type="text" id="hidden-text-input">
<div class="row"><div> <div class="row"><div>
<h1>The Inter UI font family</h1> <h1>The Inter UI font family</h1>
@ -46,8 +63,17 @@ layout: default
<p>&nbsp;</p> <p>&nbsp;</p>
<h2><a href="{{url_root}}dynmetrics/">Dynamic Metrics</a></h2> <h2><a href="{{url_root}}dynmetrics/">Dynamic Metrics</a></h2>
<p class="dynmet-calc">
Font size
<input id="dynmet-font-size" type="number" value="12"
><span title='Display points — "px" in CSS, "pt" on iOS, "sp" on Android, and "pt" (1/72 of an inch) in print'>dp</span>
<span class="arrow">—></span>
letter spacing
<input id="dynmet-tracking" type="number" value="0.008">
<span id="dynmet-unit">em</span>
</p>
<p> <p>
There's of course no absolute right or wrong when it comes to expressing yourself with typography, but Inter UI <em>Dynamic Metrics</em> provides guidelines for good typography. You simply provide the optical font size, and the tracking and leading is calculated for you to produce the best results. There's of course no absolute right or wrong when it comes to expressing yourself with typography, but Inter UI <em>Dynamic Metrics</em> provides guidelines for good typography. You simply provide the optical font size, and the tracking and leading is calculated for you to produce the best results.<br>
<a href="{{url_root}}dynmetrics/">Learn about Dynamic Metrics —></a> <a href="{{url_root}}dynmetrics/">Learn about Dynamic Metrics —></a>
</p> </p>
@ -297,9 +323,11 @@ layout: default
<a href="https://twitter.com/rsms" class="plain">@rsms</a> <a href="https://twitter.com/rsms" class="plain">@rsms</a>
</div></div> </div></div>
<script>(function(){ <script>
// FAQ anchors // FAQ anchors
(function(){
var av = document.querySelectorAll('ul.faq > li.q'), a, i, e, id, tn var av = document.querySelectorAll('ul.faq > li.q'), a, i, e, id, tn
for (i = 0; i < av.length; ++i) { for (i = 0; i < av.length; ++i) {
e = av[i] e = av[i]
@ -323,4 +351,96 @@ layout: default
e.insertBefore(tn, e.firstChild) e.insertBefore(tn, e.firstChild)
} }
})();
// dynamic metrics calculator
(function(){
var hiddenTextInput = $('#hidden-text-input')
var fontSizeEl = $('#dynmet-font-size')
var trackingEl = $('#dynmet-tracking')
var unitEl = $('#dynmet-unit')
var unitFormatters = [
['em', 'em', function(fontSize, tracking) {
return tracking.toFixed(3)
}],
['px', 'px', function(fontSize, tracking) {
return (fontSize * tracking).toFixed(3)
}],
['%', 'percent', function(fontSize, tracking) {
return (tracking * 100).toFixed(1)
}],
]
var unitFormatter = unitFormatters[0][2]
function updateTracking() {
var fontSize = parseFloat(fontSizeEl.value)
if (isNaN(fontSize) || fontSize < 1) {
fontSizeEl.value = fontSize = 1
} else if (fontSize > 999) {
fontSizeEl.value = fontSize = 999
}
var tracking = InterUIDynamicTracking(fontSize)
trackingEl.value = unitFormatter(fontSize, tracking)
}
function toggleUnit() {
var unit = unitEl.innerText
var u, x = -1
for (var i = 0; i < unitFormatters.length; i++) {
if (x == -1) {
u = unitFormatters[i]
if (u[0] == unit) {
x = i + 1
if (x == unitFormatters.length) {
x = 0
}
u = unitFormatters[x]
}
}
trackingEl.classList.remove(unitFormatters[i][1]) // class name
}
unit = u[0]
trackingEl.classList.add(u[1])
unitFormatter = u[2]
unitEl.innerText = unit
updateTracking()
}
function onPointerdownUnit(ev) {
toggleUnit()
if (ev) {
ev.preventDefault()
ev.stopPropagation()
}
}
function onPointerdownTracking(ev) {
if (ev) {
ev.preventDefault()
ev.stopPropagation()
}
hiddenTextInput.value = trackingEl.value + unitEl.innerText
hiddenTextInput.select()
document.execCommand("copy")
trackingEl.select()
HUDNotification.show('Copied to clipboard')
}
var passiveListener = { passive: true, capture: false }
var activeListener = { capture: true }
fontSizeEl.addEventListener('input', updateTracking, passiveListener)
fontSizeEl.addEventListener('change', updateTracking, passiveListener)
unitEl.addEventListener('pointerdown', onPointerdownUnit, activeListener)
unitEl.addEventListener('mousedown', onPointerdownUnit, activeListener)
trackingEl.addEventListener('pointerdown', onPointerdownTracking, activeListener)
trackingEl.addEventListener('mousedown', onPointerdownTracking, activeListener)
updateTracking()
})();</script> })();</script>

View file

@ -269,8 +269,8 @@ h1 > a, h2 > a, h3 > a {
color: #aaa; color: #aaa;
} }
.row.dark a:hover { .row.dark a:hover {
color: rgba(160, 190, 255, 1); color: rgb(95, 170, 255);
text-decoration: underline rgba(164, 188, 255, 0.6); text-decoration: underline rgb(95, 170, 255);
} }
.row.dark h2, .row.dark h2 > a { .row.dark h2, .row.dark h2 > a {
color: #ccc; color: #ccc;
@ -467,6 +467,35 @@ box h3 {
margin-bottom:0.8em; margin-bottom:0.8em;
} }
#hud-notification {
position: fixed;
bottom: 20px;
left: 0;
right: 0;
display: flex;
justify-content: center;
z-index: 9;
pointer-events: none;
}
#hud-notification .msg {
background: #000;
color: white;
height: 50px;
line-height: 50px;
font-size: 22px;
letter-spacing: -0.012em;
padding: 0 0.7em;
border-radius: 4px;
opacity: 0.1;
transition: 250ms all ease-in;
transform: translate3d(0, 71px, 0); /* height + bottom offset + 1 */
}
#hud-notification.visible .msg {
transform: translate3d(0, 0, 0);
transition: 120ms all cubic-bezier(0.25, 0.47, 0.44, 0.93);
opacity: 1;
}
/* ------------------------------------------------------ */ /* ------------------------------------------------------ */

View file

@ -48,6 +48,44 @@ var timeNow = (
) )
var HUDNotification = {
el: $('#hud-notification'),
timer: null,
visible: false,
show: function(message, duration) {
var n = this
n.el.firstChild.innerText = message
n.el.classList.add('visible')
if (n.visible) {
n.hide()
setTimeout(function(){ n.show(message, duration) }, 120)
return
}
n.visible = true
clearTimeout(n.timer)
n.timer = setTimeout(function(){ n.hide() }, duration || 1200)
},
hide: function() {
var n = this
if (n.visible) {
n.el.classList.remove('visible')
n.visible = false
}
}
}
// InterUIDynamicTracking takes the font size in points or pixels and returns
// the compensating tracking in EM.
//
function InterUIDynamicTracking(fontSize) {
// tracking = a + b * e ^ (c * fontSize)
return -0.016 + 0.21 * Math.pow(Math.E, -0.18 * fontSize)
}
// Mac or not? Maybe even a buggy Safari? // Mac or not? Maybe even a buggy Safari?
var isMac = false var isMac = false
if (!window.MSStream && if (!window.MSStream &&