website: major update

This commit is contained in:
Rasmus Andersson 2018-02-20 01:38:51 -08:00
parent 761638ef42
commit 9f367901ef
22 changed files with 2139 additions and 1030 deletions

1
.gitignore vendored
View file

@ -17,6 +17,7 @@ nohup.out
build
/_*
/docs/lab/fonts
/docs/_site
src/FontInspector.html
src/svg

View file

@ -159,13 +159,13 @@ install_otf: all_otf
install: install_otf
geninfo: docs/info.json docs/lab/glyphinfo.json docs/glyphs/metrics.json
geninfo: docs/_data/fontinfo.json docs/lab/glyphinfo.json docs/glyphs/metrics.json
src/glyphorder.txt: src/Inter-UI-Regular.ufo/lib.plist src/Inter-UI-Black.ufo/lib.plist src/diacritics.txt misc/gen-glyphorder.py
misc/gen-glyphorder.py src/Inter-UI-*.ufo > src/glyphorder.txt
docs/info.json: misc/fontinfo.py docs/font-files/Inter-UI-*.otf
misc/fontinfo.py -pretty docs/font-files/Inter-UI-Regular.otf > docs/info.json
docs/_data/fontinfo.json: misc/fontinfo.py docs/font-files/Inter-UI-*.otf
misc/fontinfo.py -pretty docs/font-files/Inter-UI-Regular.otf > docs/_data/fontinfo.json
docs/lab/glyphinfo.json: _local/UnicodeData.txt src/glyphorder.txt src/fontbuild.cfg misc/gen-glyphinfo.py
misc/gen-glyphinfo.py -ucd _local/UnicodeData.txt \

10
docs/_config.yml Normal file
View file

@ -0,0 +1,10 @@
port: 3000
lsi: false
permalink: /:title
markdown: kramdown
# Since GH pages override this to "true", we test this value to see if we are running locally
safe: false
kramdown:
input: GFM
auto_ids: true
hard_wrap: false

View file

@ -1,5 +1,5 @@
{
"Inter UI Regular:2018:86daccf": {
[
{
"head": {
"checkSumAdjustment": 3690365233,
"created": 3563720514,
@ -117,6 +117,7 @@
"minMemType42": 0,
"underlinePosition": -422,
"underlineThickness": 170
}
},
"version": "2.5"
}
}
]

View file

@ -0,0 +1,46 @@
{% if site.safe == false %}
<!-- During authoring, this automatically reloads the post as its changing -->
<script type="text/javascript">
(function() {
var qs = document.location.search;
var current_etag = qs.match(/etag=("?[a-zA-Z0-9_-]+)/);
if (current_etag !== null) { current_etag = current_etag[1]; }
var scrolly = qs.match(/scrolly=([0-9]+)/);
if (scrolly) {
scrolly = parseInt(scrolly[1]);
if (scrolly > 0) {
window.scrollTo(window.scrollX, scrolly);
setTimeout(function () {
window.scrollTo(window.scrollX, scrolly);
}, 10);
}
}
function check() {
var r = new XMLHttpRequest();
var url = document.location.href + ((qs && qs !== '') ? '&' : '?') + 'r=' + Math.random();
r.open('GET', url, true);
r.onreadystatechange = function() {
if (r.readyState == 4){
var found_etag = r.getResponseHeader('Etag');
if (found_etag) {
found_etag = found_etag.replace(/^"|"$/g);
}
//console.log('current_etag:', current_etag, 'found_etag:', found_etag);
if (current_etag === null) {
current_etag = found_etag;
} else if (found_etag !== current_etag) {
document.location.search =
'?etag=' + encodeURIComponent(found_etag) +
'&scrolly=' + window.scrollY;
return;
}
setTimeout(check, 500);
}
};
r.send(null);
}
check();
})();
</script>
{% endif %}

View file

@ -0,0 +1,88 @@
{%
assign build_version = site.time | date: "%Y%m%d%H%M%S" %}{%
assign description = "Inter UI is a new typeface optimized for computer user interfaces" %}{%
capture url_root
%}{% if site.safe == false %}/{% else %}/inter/{% endif
%}{%
endcapture %}{%
capture release_version
%}{{ site.data.fontinfo[0].version }}{%
endcapture %}{%
capture download_url
%}https://github.com/rsms/inter/releases/download/v{{ release_version }}/Inter-UI-{{ release_version }}.zip{%
endcapture %}{%
for file in site.static_files %}{%
assign _path = file.path | remove_first: "/inter" %}{%
if _path == "/res/base.css" %}{%
assign base_css_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
elsif _path == "/res/base.js" %}{%
assign base_js_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
endif %}{%
endfor
%}<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{% if page.title %}{{ page.title }} — Inter UI{% else %}Inter UI font family{% endif %}</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="stylesheet" href="{{url_root}}inter-ui.css?v={{ release_version }}">
<link rel="stylesheet" href="{{url_root}}res/base.css?v={{ base_css_v }}">
<link rel="icon" type="image/png" href="{{url_root}}res/favicon.png">
<meta name="format-detection" content="telephone=no">
<meta property="twitter:card" content="summary">
<meta property="twitter:site" content="@rsms">
<meta property="twitter:creator" content="@rsms">
<meta property="description" content="{{description}}">
<meta property="og:description" content="{{description}}">
<meta property="twitter:description" content="{{description}}">
{% if page.title %}
<meta property="og:title" content="{{ page.title }}">
<meta property="twitter:title" content="{{ page.title }}">
{% endif %}
{% if page.og_image_url %}
<meta property="og:image" content="{{ page.og_image_url }}">
<meta property="twitter:image" content="{{ page.og_image_url }}">
{% else %}
<meta property="og:image" content="https://rsms.me/inter/res/poster.png">
<meta property="twitter:image" content="https://rsms.me/inter/res/poster.png">
{% endif %}
<meta property="og:url" content="https://rsms.me/inter/{{ page.url | remove_first:'index.html' }}">
<meta property="fb:app_id" content="38027689216">
<meta property="og:site_name" content="rsms.me/inter">
<meta property="og:type" content="product">
<meta property="og:locale" content="en_US" />
</head>
<body>
<script src="{{url_root}}res/base.js?v={{ base_js_v }}"></script>
<div class="row menu">
<ul class="menu">
<li class="home"><a href="{{url_root}}">Inter UI</a></li>
<li><a class="download-link" href="{{ download_url }}"
>Download</a></li>
<li><a href="{{url_root}}samples/"
{% if page.url contains "/samples/" %}class="active"{% endif %}
>Samples</a></li>
<li><a href="{{url_root}}lab/"
{% if page.url contains "/lab/" %}class="active"{% endif %}
>Playground</a></li>
<li><a href="https://github.com/rsms/inter/"
>Source</a></li>
</ul>
</div>
{{ content }}
{% if site.safe == true %}
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-105091131-2"></script>
{% endif %}
{% include autoreload-in-debug.html %}
</body>
</html>

View file

@ -1,6 +1,6 @@
#!/bin/sh
set -e
cd "$(dirname "$0")"
cd "$(dirname "$0")/.."
pushd res >/dev/null

9
docs/_scripts/serve.sh Executable file
View file

@ -0,0 +1,9 @@
#!/bin/sh
set -e
cd "$(dirname "$0")/.."
if [ ! -s lab/fonts ]; then
ln -s ../../build/dist lab/fonts
fi
jekyll serve --limit_posts 20 --watch --host 127.0.0.1 --port 3002 --open-url

262
docs/dynmetrics/index.css Normal file
View file

@ -0,0 +1,262 @@
body {
padding-bottom: 0;
}
const {
display: inline;
font-size: 1.2em;
font-style: italic;
font-family: 'Times New Roman', Times, serif;
}
sup {
/*background:lightpink;*/
display: inline-block;
font-size:0.92em;
position: relative;
top:-0.4em;
letter-spacing: 0.001em;
vertical-align: baseline;
}
.row.first {
padding-bottom:1em;
}
formula {
display: inline-flex;
align-items: center;
background: white;
border-radius: 5px;
padding: 0 1em;
line-height: 3em;
height: 3em;
overflow: hidden;
margin-right: 1em;
margin-bottom: 1em;
}
.row.white formula {
background: #f5f5f5;
}
formula:last-child {
margin-right: 0;
}
formula.code {
white-space: pre;
font-family: "SFMono-Regular", Menlo, Consolas, Inconsolata, monospace;
font-size:0.96em;
}
formula > * {
margin: 0 0.2em 0 0.2em;
}
formula > const {
margin-bottom: 0.11em;
}
formula > sup {
margin-left: 0;
}
.samples {
display: flex;
flex-wrap: wrap;
overflow: auto;
overflow-wrap: break-word;
word-break: break-word;
}
.samples .sample {
/*background: lightpink;*/
color: #111;
flex: 0 1 auto;
outline: none;
margin-right: 50px;
margin-bottom: 50px;
}
.samples .sample .di {
display: block;
background-color: #ccc;
height: 1px;
width: 100%;
margin-bottom: 8px;
}
.samples .sample .di > span {
display: block;
background-color: #333;
height: 100%;
}
.samples .sample .di.match > span {
background-color: #0d3;
}
.samples .sample .di.unavailable {
background-color: #eee;
}
.samples .sample .di.unavailable > span {
visibility: hidden;
}
.samples .sample .info {
display: block;
font-size: 11px !important;
line-height: 11px;
margin-bottom: 9px;
color: #bbb;
}
.font-style-regular { font-weight:400 !important; font-style:normal !important; }
.font-style-italic { font-weight:400 !important; font-style:italic !important; }
.font-style-medium { font-weight:500 !important; font-style:normal !important; }
.font-style-medium-italic { font-weight:500 !important; font-style:italic !important; }
.font-style-bold { font-weight:700 !important; font-style:normal !important; }
.font-style-bold-italic { font-weight:700 !important; font-style:italic !important; }
.font-style-black { font-weight:900 !important; font-style:normal !important; }
.font-style-black-italic { font-weight:900 !important; font-style:italic !important; }
.row.with-sidebar {
padding: 0;
}
.row.with-sidebar > *:first-child {
flex: 1 1 auto;
padding: 50px 0 0 50px; /* note: samples have 50px right margin */
}
.row.with-sidebar > .sidebar {
flex: 0 0 auto;
}
div.controls {
box-sizing: border-box;
width: 250px;
max-width: 250px;
flex: 0 0 auto;
padding: 10px 0;
border-left: 4px solid #f4f4f4;
display: flex;
flex-direction: column;
overflow: hidden;
}
div.controls hr {
border: none;
height: 2px;
background: #f4f4f4;
margin-top: 10px;
margin-bottom: 10px;
}
div.controls hr.without-bottom-margin { margin-bottom: 0; }
div.controls hr.without-top-margin { margin-top: 0; }
div.controls hr.without-margins { margin: 0; }
div.controls .control {
display: flex;
justify-content: space-between;
align-items: center;
overflow: hidden;
height: 30px;
margin: 0 16px;
}
div.controls > h3 {
margin: 0 16px;
}
div.controls > textarea {
border: none;
padding:16px;
height: 400px;
font-family: "SFMono-Regular", Menlo, Consolas, Inconsolata, monospace;
outline: none;
}
div.controls .control > * {
/*max-width: 50%;*/
flex: 1 1 auto;
margin:0;
margin-right: 16px;
box-sizing: border-box;
}
div.controls .control > :last-child {
margin-right: 0;
}
div.controls .control > select {
min-width: 6em;
align-items: center;
justify-content: center;
}
div.controls .control > input,
div.controls .control > select {
width: 0;
outline: none;
}
div.controls .control > input[type="number"],
div.controls .control > input[type="text"] {
background: none;
border: none;
padding: 4px 0;
font-size: 13px;
}
div.controls .control > input[type="number"] {
max-width: 60px;
-moz-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
-ms-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
-o-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
-webkit-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
}
div.controls .control > input[type=number]::-webkit-inner-spin-button,
div.controls .control > input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
div.controls .control > input[type="number"][readonly] {
max-width: 40px;
}
div.controls .control > input.wide[type="number"] {
max-width: 100%;
}
div.controls .control > input[type="range"] {
/*max-width: 80%;*/
flex: 1 1 auto;
display: block;
}
div.controls .control > img.icon,
div.controls .control > label {
font-family: georgia, serif;
font-style: italic;
line-height: 16px;
color: black;
width: 16px;
height: 16px;
flex: 0 0 auto;
margin-right: 16px;
opacity: 0.6;
}
div.controls canvas {
height: 200px;
}
.row.small-window {
margin-top:0;
padding-top:0;
}
@media only screen and (min-width: 541px) {
.small-window {
display: none;
}
}
@media only screen and (max-width: 540px) {
.row.with-sidebar {
overflow: auto;
}
div.controls {
display: none;
}
div.controls .graphplot,
div.controls hr.without-top-margin,
div.controls h3,
div.controls #ideal-values
{
display: none;
}
.row.with-sidebar {
flex-direction: column;
}
}

522
docs/dynmetrics/index.html Normal file
View file

@ -0,0 +1,522 @@
---
layout: default
title: Dynamic Metrics
---
{%
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 == "/dynmetrics/index.css" %}{%
assign index_css_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
elsif _path == "/res/bindings.js" %}{%
assign bindings_js_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
elsif _path == "/res/graphplot.js" %}{%
assign graphplot_js_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
endif %}{%
endfor
%}
<link rel="stylesheet" href="index.css?v={{ index_css_v }}">
<script src="{{url_root}}res/bindings.js?v={{ bindings_js_v }}"></script>
<script src="{{url_root}}res/graphplot.js?v={{ graphplot_js_v }}"></script>
<div class="row first"><div>
<h1>Dynamic Metrics</h1>
<p>
There's of course no absolute right or wrong when it comes to expressing
yourself with typography, but Inter UI Dynamic Metrics provides guidelines
for <em>good</em> typography.
You simply provide the optical font size, and the tracking and leading
(letter spacing and line height) will be calculated using the following
formula:
</p>
<p>
<formula>
tracking =
<const>a</const> + <const>b</const> ×
<const>e</const><sup>(<const>c</const> × fontSize)</sup>
</formula>
<formula>
leading = <const>l</const> × fontSize
</formula>
<formula>
<const>e</const><num>2.718</num>
</formula>
</p>
<p class="small-window">
<small>View this on a larger screen to enable interactive control.</small>
</p>
</div></div>
<!-- <div class="row small-window"><div>
Hello
</div></div> -->
<div class="white full-width row with-sidebar">
<div class="samples">
<p contenteditable class="sample">
<span class="di"><span></span></span>
<span class="info"
title="size, tracking, (ideal tracking) — progress bar shows distance from ideal"
>15 &nbsp; 0.0 &nbsp; ( 0.0 )</span>
Such a riot of sea and wind strews the whole extent of beach with whatever has been lost or thrown overboard, or torn out of sunken ships. Many a man has made a good weeks work in a single day by what he has found while walking along the Beach when the surf was down.
</p>
</div>
<div class="sidebar controls">
<div class="control">
<label title="Number of ideal matches">ni</label>
<input title="Number of ideal matches" type="number" readonly data-binding="ideal-count">
<label title="Distance from ideal">di</label>
<input title="Distance from ideal" type="number" class="wide" readonly data-binding="ideal-distance">
</div>
<div class="control">
<img title="Style" class="icon" src="../samples/icons/style.svg">
<select data-binding="style">
<option value="regular" default>Regular</option>
<option value="italic">Italic</option>
<option value="medium" default>Medium</option>
<option value="medium-italic">Medium Italic</option>
<option value="bold" default>Bold</option>
<option value="bold-italic">Bold Italic</option>
<option value="black" default>Black</option>
<option value="black-italic">Black Italic</option>
</select>
</div>
<div class="control">
<img title="Base tracking" class="icon" src="../samples/icons/letter-spacing.svg">
<input type="range" min="-0.05" max="0.06" step="0.001" data-binding="base-tracking">
<input type="number" min="-0.15" max="1" step="0.001" data-binding="base-tracking">
</div>
<hr>
<div class="control">
<label title="Constant a">a</label>
<input type="range" min="-0.05" max="0" step="0.001" data-binding="var-a">
<input type="number" min="-0.05" max="0" step="0.0001" data-binding="var-a">
</div>
<div class="control">
<label title="Constant b">b</label>
<input type="range" min="0" max="1" step="0.01" data-binding="var-b">
<input type="number" min="0" max="1" step="0.001" data-binding="var-b">
</div>
<div class="control">
<label title="Constant c">c</label>
<input type="range" min="-1" max="0" step="0.01" data-binding="var-c">
<input type="number" min="-1" max="0" step="0.001" data-binding="var-c">
</div>
<hr>
<div class="control">
<label title="Constant l controls line height">l</label>
<input type="range" min="1" max="2" step="0.1" data-binding="var-l">
<input type="number" min="1" max="2" step="0.1" data-binding="var-l">
</div>
<hr class="without-bottom-margin">
<canvas class="graphplot">Canvas not Supported</canvas>
<hr class="without-top-margin">
<h3>Ideal values</h3>
<textarea id="ideal-values"></textarea>
<hr class="without-top-margin">
</div>
</div>
<script type="text/javascript">(function(){
// internal variables that are user-controllable, but are not part of
// Dynamic Metrics
var baseTracking = 0
var weightClass = 400
// Ideal values designed one by one, by hand.
// font size => tracking
var idealValues = {}
var idealValuesList = []
var idealValuesTextArea = $('textarea#ideal-values')
function setIdealValues(valueMap) {
idealValues = valueMap
idealValuesList = []
Object.keys(idealValues).forEach(function(fontSize) {
idealValuesList.push([fontSize, idealValues[fontSize]])
})
if (idealValuesTextArea.value == '') {
idealValuesTextArea.value = idealValuesList.map(function(t){
return t[0] + '\t' + t[1]
}).join('\n')
}
}
function parseValues(s) {
var values = {}
s = s.replace(/^[\s\r\t\n]+|[\s\r\t\n]+$/g, '') // trim whitespace
s.split(/\s*\r?\n\s*/).map(function(line) {
var t = line.split(/\s+/)
if (t.length == 2) {
t[0] = parseInt(t[0])
t[1] = parseFloat(t[1])
values[t[0]] = t[1]
}
})
return values
}
setIdealValues({
// set-2018-02-20
6: 0.055,
7: 0.044,
8: 0.034,
9: 0.024,
10: 0.018,
11: 0.012,
12: 0.007,
13: 0.003,
14: 0.001,
15: -0.002,
16: -0.004,
17: -0.006,
18: -0.008,
20: -0.01,
24: -0.013,
})
// setIdealValues({
// // set-2018-02-19
// 6: 0.059,
// 7: 0.043,
// 8: 0.032,
// 9: 0.022,
// 10: 0.014,
// 11: 0.009,
// 12: 0.004,
// 13: 0,
// 14: -0.003,
// 15: -0.005,
// 16: -0.0075,
// 17: -0.0084,
// 18: -0.0095,
// 20: -0.012,
// 24: -0.014,
// })
// setIdealValues({
// // set-2018-02-18
// 6: 0.06,
// 7: 0.04,
// 8: 0.03,
// 9: 0.02,
// 10: 0.01,
// 11: 0.005,
// 12: 0.002,
// 13: 0.001,
// 14: 0,
// 15: -0.002,
// 16: -0.005,
// 17: -0.007,
// 18: -0.009,
// 20: -0.011,
// 24: -0.011,
// })
// Variables for constants involved in Dynamic Metrics
var a = -0.013
// -0.0119
// -0.0101
// -0.0092
// -0.012
// -0.013
var b = 0.23
// 0.455
// 0.421
// 0.26
// 0.23
// 0.251
var c = -0.21
// -0.29
// -0.23
// -0.21
// -0.222
// a = -0.012; b = 0.23; c = -0.21; // di=0.002514 on set-2018-02-18
// a = -0.013; b = 0.251; c = -0.222 // di=0.001742 on set-2018-02-18
// a = -0.015; b = 0.283; c = -0.23; // di=0.00221 on set-2018-02-18
// a = -0.0149; b = 0.298; c = -0.23; // di=0.000484 on set-2018-02-19
a = -0.016; b = 0.21; c = -0.18; // di=0.000532 on set-2018-02-20
// these have a short di, but stray far away from larger font sizes
// a = -0.0077
// b = 0.377
var l = 1.4
// InterUIDynamicTracking takes the font size in points or pixels and returns
// the compensating tracking in EM.
//
function InterUIDynamicTracking(fontSize, weightClass) {
// if (!weightClass) { -- currently unused
// weightClass = 400
// }
//
// y = -0.01021241 + 0.3720623 * e ^ (-0.2808687 * x)
// [6-35] 0.05877 .. -0.0101309 (13==0; stops growing around 30-35)
// See https://gist.github.com/rsms/8efdbca5f8145a584ed08a7c3d6e5788
//
return a + b * Math.pow(Math.E, c * fontSize)
// [6 - 38] 0.05798 .. -0.01099 (midpoint = 12.533)
// y = 0.025 - (ln(x) * 0.01)
// return 0.025 - Math.log(fontSize) * 0.01
}
function InterUIDynamicLineHeight(fontSize, weightClass) {
return Math.round(fontSize * l)
}
var NPOS = Number.MAX_SAFE_INTEGER
function Sample(fontSize) {
this.rootEl = sampleTemplate.cloneNode(true)
this.infoEl = $('.info', this.rootEl)
this.diEl = $('.di', this.rootEl)
this.diEl.classList.add('unavailable')
this.style = this.rootEl.style
this.maxBoxWidth = 0
this.fontSize = 0
this.tracking = 0
this.lineHeight = 0
this.idealTracking = NPOS
this.matchesIdeal = false
this.setFontSize(fontSize)
this.render()
}
Sample.prototype.idealDistance = function(fontSize) {
// returns the distance from the ideal (or NPOS if no "ideal" data available)
if (this.idealTracking == NPOS) {
return NPOS
}
return (
Math.max(this.tracking, this.idealTracking) -
Math.min(this.tracking, this.idealTracking)
)
}
Sample.prototype.setFontSize = function(fontSize) {
this.fontSize = fontSize
this.tracking = baseTracking + InterUIDynamicTracking(fontSize, weightClass)
this.lineHeight = InterUIDynamicLineHeight(fontSize, weightClass)
this.maxBoxWidth = Math.round(fontSize * (this.tracking + 1) * 25)
var idealTracking = idealValues[this.fontSize]
if (idealTracking === undefined) {
if (this.idealTracking != NPOS) {
this.diEl.classList.add('unavailable')
}
this.idealTracking = NPOS
this.matchesIdeal = false
} else {
if (this.idealTracking == NPOS) {
this.diEl.classList.remove('unavailable')
}
this.idealTracking = idealTracking
// match to a precision of 3
this.matchesIdeal = this.tracking.toFixed(3) == idealTracking.toFixed(3)
var di = 1
if (this.matchesIdeal) {
this.diEl.classList.add('match')
} else {
this.diEl.classList.remove('match')
di = 1 - Math.min(1, this.idealDistance() * 50)
}
this.diEl.firstChild.style.width = (di * this.maxBoxWidth) + 'px'
}
}
Sample.prototype.render = function() {
this.style.fontSize = this.fontSize + 'px'
this.style.letterSpacing = this.tracking + 'em'
this.style.lineHeight = this.lineHeight + 'px'
var SP = '\u00A0\u00A0\u00A0'
this.infoEl.innerText = (
this.fontSize +
SP + this.tracking.toFixed(3) +
// SP + this.lineHeight.toFixed(3) +
(
this.idealTracking != NPOS ? (
SP + '( ' + this.idealTracking +
(this.matchesIdeal ? ' \u2713' : '') +
' )'
) : ''
)
)
this.style.maxWidth = this.maxBoxWidth + 'px'
}
var bindings = new Bindings()
var sampleTemplate
var samples = [] // Sample[]
var graph = new GraphPlot($('canvas.graphplot'))
graph.setOrigin(-0.2, 0.8)
graph.setScale(0.049, 5)
function addChildren(targetNode, children) {
targetNode.style.visibility = 'hidden'
var i = 0;
for (; i < children.length; i++) {
targetNode.appendChild(children[i])
}
targetNode.style.visibility = null
}
function initSamples() {
var samplesEl = $('.samples')
sampleTemplate = $('.sample', samplesEl)
samplesEl.removeChild(sampleTemplate)
// small and medium sizes
var i, fontSize = 6, endFontSize = 16
for (; fontSize <= endFontSize; fontSize++) {
samples.push(new Sample(fontSize))
}
// a few select large samples
samples.push(new Sample(17))
samples.push(new Sample(18))
samples.push(new Sample(20))
samples.push(new Sample(24))
samples.push(new Sample(30))
samples.push(new Sample(40))
// add to dom in one go
addChildren(samplesEl, samples.map(function(s) { return s.rootEl }))
}
function updateSample(sample) {
sample.setFontSize(sample.fontSize) // updates derived values
sample.render()
}
function updateSamples() {
samples.forEach(updateSample)
updateIdealMatches()
updateGraphPlot()
}
function updateIdealMatches() {
// ideal-distance
var idealCount = 0
var distance = 0
var ndistances = 0
samples.forEach(function(sample) {
if (sample.matchesIdeal) {
idealCount++
}
var di = sample.idealDistance()
if (di != NPOS) {
distance += di
ndistances++
}
})
distance = distance / ndistances
bindings.setValue('ideal-distance', distance.toFixed(6))
bindings.setValue('ideal-count', idealCount)
}
function updateGraphPlot() {
graph.clear()
graph.plotLine(idealValuesList, '#0d3')
graph.plotf(function(x) {
return InterUIDynamicTracking(x, weightClass)
})
}
bindings.configure('base-tracking', 0, 'float', function (tracking) {
baseTracking = tracking
updateSamples()
})
bindings.configure('var-a', a, 'float', function (v) {
a = v
updateSamples()
})
bindings.configure('var-b', b, 'float', function (v) {
b = v
updateSamples()
})
bindings.configure('var-c', c, 'float', function (v) {
c = v
updateSamples()
})
bindings.configure('var-l', l, 'float', function (v) {
l = v
updateSamples()
})
bindings.configure('ideal-count', 0, 'int', function (v) {})
bindings.configure('ideal-distance', 0, 'float', function (v) {})
bindings.configure('style', null, null, function (style) {
var cl = $('.samples').classList
cl.remove('font-style-regular')
cl.remove('font-style-italic')
cl.remove('font-style-medium')
cl.remove('font-style-medium-italic')
cl.remove('font-style-bold')
cl.remove('font-style-bold-italic')
cl.remove('font-style-black')
cl.remove('font-style-black-italic')
cl.add('font-style-' + style)
weightClass = (
style.indexOf('black') != -1 ? 900 :
style.indexOf('bold') != -1 ? 700 :
style.indexOf('medium') != -1 ? 500 :
400
)
updateSamples()
})
bindings.bindAllInputs('.control input')
bindings.bindAllInputs('.control select')
// double-click base tracking to reset
$('input[type="range"][data-binding="base-tracking"]').addEventListener(
'dblclick',
function(ev) { bindings.setValue('base-tracking', 0) }
)
// allow editing of ideal values
idealValuesTextArea.addEventListener('input', function(ev) {
setIdealValues(parseValues(idealValuesTextArea.value))
updateSamples()
})
// start
initSamples()
updateSamples()
})();</script>

View file

@ -1,39 +1,27 @@
<!DOCTYPE HTML>
<html lang="en" prefix="og: http://ogp.me/ns#">
<head>
<meta charset="utf-8">
<title>Repertoire Inter UI font family</title>
---
layout: default
title: Glyphs
---
{%
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
capture url_root
%}{% if site.safe == false %}/{% else %}/inter/{% endif
%}{%
endcapture %}{%
<meta property="og:title" content="Inter UI font family">
<meta property="twitter:title" content="Inter UI font family">
<meta property="description" content="Inter UI is a new typeface optimized for computer user interfaces">
<meta property="og:description" content="Inter UI is a new typeface optimized for computer user interfaces">
<meta property="twitter:description" content="Inter UI is a new typeface optimized for computer user interfaces">
<meta property="twitter:card" content="summary">
<meta property="twitter:site" content="@rsms">
<meta property="twitter:creator" content="@rsms">
<meta property="og:image" content="https://rsms.me/inter/res/poster.png">
<meta property="twitter:image" content="https://rsms.me/inter/res/poster.png">
for file in site.static_files %}{%
assign _path = file.path | remove_first: "/inter" %}{%
if _path == "/glyphs/glyphs.css" %}{%
assign glyphs_css_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
elsif _path == "/glyphs/glyphs.js" %}{%
assign glyphs_js_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
endif %}{%
endfor
<meta property="fb:app_id" content="38027689216">
<meta property="fb:admins" content="728642302">
<meta property="og:url" content="https://rsms.me/inter/">
<meta property="og:site_name" content="rsms.me">
<meta property="og:type" content="product">
<meta property="og:locale" content="en_US" />
%}
<link rel="icon" type="image/png" href="../favicon.png" />
<link href="../inter-ui.css" rel="stylesheet">
<link href="../index.css" rel="stylesheet">
<link href="glyphs.css" rel="stylesheet">
</head>
<body>
<script src="../index.js"></script>
<div id="svgs">
<link rel="stylesheet" href="glyphs.css?v={{ glyphs_css_v }}">
<div id="svgs">
<svg id="svg-A" xmlns="http://www.w3.org/2000/svg" width="176" height="348"><path d="M146 -76.8 L44.8 -76.8 L44.8 -54.8 L146 -54.8z M33.2 0 L94 -172.4 L96.4 -172.4 L157.2 0 L183.2 0 L108 -204.8 L82.4 -204.8 L7.2 0z" transform="translate(-7.2 281.6)"/></svg>
<svg id="svg-AE" xmlns="http://www.w3.org/2000/svg" width="264" height="348"><path d="M142.4 -186 L144.8 -204.8 L127.2 -204.8 L6 0 L35.6 0z M164 -76.8 L60.4 -76.8 L60.4 -55.2 L164 -55.2z M269.2 -22 L168.4 -22 L168.4 0 L269.2 0z M164.8 -204.8 L140.4 -204.8 L148.8 0 L173.2 0z M249.6 -115.2 L162.8 -115.2 L162.8 -93.2 L249.6 -93.2z M260.8 -204.8 L160 -204.8 L160 -182.8 L260.8 -182.8z" transform="translate(-6 281.6)"/></svg>
<svg id="svg-AEacute" xmlns="http://www.w3.org/2000/svg" width="264" height="348"><path d="M142.4 -186 L144.8 -204.8 L127.2 -204.8 L6 0 L35.6 0z M164 -76.8 L60.4 -76.8 L60.4 -55.2 L164 -55.2z M269.2 -22 L168.4 -22 L168.4 0 L269.2 0z M164.8 -204.8 L140.4 -204.8 L148.8 0 L173.2 0z M249.6 -115.2 L162.8 -115.2 L162.8 -93.2 L249.6 -93.2z M260.8 -204.8 L160 -204.8 L160 -182.8 L260.8 -182.8z M135.2 -223.2 L152.8 -223.2 L183.6 -264 L159.2 -264z" transform="translate(-6 281.6)"/></svg>
@ -2222,37 +2210,34 @@
<svg id="svg-zrthook" xmlns="http://www.w3.org/2000/svg" width="151" height="348"><path d="M112.8 -16.8 L112.8 19.2 C112.8 45.6 130.4 60 153.2 60 C157.6 60 163.2 59.6 166.8 58.4 L166.8 38 C164.8 38.8 161.2 38.8 159.2 38.8 C146.4 38.8 136.4 35.2 136.4 19.2 L136.4 -16.8z M136.4 -22 L28 -22 L28 0 L136.4 0z M134.4 -134.8 L134.4 -153.6 L120.8 -153.6 L17.6 -20 L17.6 0 L31.6 0z M122.4 -153.6 L16 -153.6 L16 -131.6 L122.4 -131.6z" transform="translate(-16 281.6)"/></svg>
</div><!--END-SVGS don't remove this comment-->
<div class="row intro"><div>
<h2 class="back"><a href="../">The Inter UI font family</a></h2>
<h1><a href="./">Inter UI glyphs</a></h1>
<p>
This shows the complete set of glyphs in Inter UI Regular.
You can zoom in and out by pressing
<kbd></kbd><kbd>+</kbd> and
<kbd></kbd><kbd></kbd> on your keyboard.
Click on a glyph to see more details about it.
</p>
</div></div>
<div class="row intro"><div>
<h1><a href="./">Glyphs</a></h1>
<p>
This shows the complete set of glyphs in Inter UI Regular.
You can zoom in and out by pressing
<kbd></kbd><kbd>+</kbd> and
<kbd></kbd><kbd></kbd> on your keyboard.
Click on a glyph to see more details about it.
</p>
</div></div>
<div id="glyphs">
<div id="single-info" style="display:none">
<ul>
<li>Glyph name: <span class="name"></span></li>
<li class="unicode">Unicode: <a><span class="unicodeCodePoint num"></span> <span class="unicodeName"></span></a></li>
<li>Advance width: <span class="advanceWidth num"></span></li>
<li>Left margin: <span class="marginLeft num"></span></li>
<li>Right margin: <span class="marginRight num"></span></li>
<li>Color mark: <span class="colorMark">&nbsp;</span></li>
<li><a class="svgFile">&darr; Download SVG file</a></li>
</ul>
</div>
</div>
<div id="glyphs">
<div id="single-info" style="display:none">
<ul>
<li>Glyph name: <span class="name"></span></li>
<li class="unicode">Unicode: <a><span class="unicodeCodePoint num"></span> <span class="unicodeName"></span></a></li>
<li>Advance width: <span class="advanceWidth num"></span></li>
<li>Left margin: <span class="marginLeft num"></span></li>
<li>Right margin: <span class="marginRight num"></span></li>
<li>Color mark: <span class="colorMark">&nbsp;</span></li>
<li><a class="svgFile">&darr; Download SVG file</a></li>
</ul>
</div>
</div>
<div class="row kerning"><div>
<h2 id="kerning"><a href="#kerning">Kerning</a></h2>
<div id="kerning-list"></div>
</div></div>
<div class="row kerning"><div>
<h2 id="kerning"><a href="#kerning">Kerning</a></h2>
<div id="kerning-list"></div>
</div></div>
<script src="glyphs.js"></script>
</body>
</html>
<script src="glyphs.js?v={{ glyphs_js_v }}"></script>

View file

@ -1,360 +1,326 @@
<!DOCTYPE HTML>
<html lang="en" prefix="og: http://ogp.me/ns#">
<head>
<meta charset="utf-8">
<title>Inter UI font family</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta property="og:title" content="Inter UI font family">
<meta property="twitter:title" content="Inter UI font family">
<meta property="description" content="Inter UI is a new typeface optimized for computer user interfaces">
<meta property="og:description" content="Inter UI is a new typeface optimized for computer user interfaces">
<meta property="twitter:description" content="Inter UI is a new typeface optimized for computer user interfaces">
<meta property="twitter:card" content="summary">
<meta property="twitter:site" content="@rsms">
<meta property="twitter:creator" content="@rsms">
<meta property="og:image" content="https://rsms.me/inter/res/poster.png">
<meta property="twitter:image" content="https://rsms.me/inter/res/poster.png">
<meta property="fb:app_id" content="38027689216">
<meta property="og:url" content="https://rsms.me/inter/">
<meta property="og:site_name" content="rsms.me">
<meta property="og:type" content="product">
<meta property="og:locale" content="en_US" />
<meta name="format-detection" content="telephone=no">
<link rel="icon" type="image/png" href="favicon.png" />
<link href="inter-ui.css?v=2.5" rel="stylesheet">
<link href="index.css?v=5" rel="stylesheet">
</head>
<body>
---
layout: default
---
<div class="row menu">
<ul class="menu">
<li class="home"><a href="../">Inter UI</a></li>
<li><a class="download-link"
href="https://github.com/rsms/inter/releases/latest/"
>Download</a></li>
<li><a href="samples/">Samples</a></li>
<li><a href="lab/">Playground</a></li>
<li><a href="https://github.com/rsms/inter/">Source</a></li>
</ul>
</div>
<div class="row"><div>
<h1>The Inter UI font family</h1>
<p>
Inter UI is a typeface specially designed for user interfaces
with focus on high legibility of small-to-medium sized text on computer screens.
</p>
<p>
The family features a tall x-height to aid in readability of mixed-case and
lower-case text. Several OpenType features are provided as well,
like contextual alternates that adjusts punctuation depending on the shape of
surrounding glyphs, slashed zero for when you need to disambiguate "0" from "o",
tabular numbers, etc.
</p>
</div></div>
<div class="row"><div>
<h1>The Inter UI font family</h1>
<p>
Inter UI is a typeface specially designed for user interfaces
with focus on high legibility of small-to-medium sized text on computer screens.
</p>
<p>
The family features a tall x-height to aid in readability of mixed-case and
lower-case text. Several OpenType features are provided as well,
like contextual alternates that adjusts punctuation depending on the shape of
surrounding glyphs, slashed zero for when you need to disambiguate "0" from "o",
tabular numbers, etc.
</p>
</div></div>
<div class="row white" style="padding-bottom:0"><div>
<p id="samples" class="samples items sample-images">
<a href="samples/" class="plain"><img src="samples/img/01.png" srcset="samples/img/01@2x.png 2x" width="888"></a>
</p>
<p style="text-align:center">
<a href="samples/" class="plain">More samples -></a>
<br><br>
</p>
</div></div>
<div class="row white" style="padding-bottom:0"><div>
<p id="samples" class="samples items">
<a href="samples/" class="plain"><img src="samples/img/01.png" srcset="samples/img/01@2x.png 2x" width="888"></a>
</p>
<p style="text-align:center">
<a href="samples/" class="plain">More samples -></a>
<br><br>
</p>
</div></div>
<div class="row dark"><div>
<div class="row dark"><div>
<h2><a id="usage" href="#usage">How do I use it?</a></h2>
<p>
Using the font is as easy as
<a class="download-link" href="https://github.com/rsms/inter/releases/latest/">download &amp; installing</a> locally on your computer.
</p>
<p>
You're free to bundle copies of Inter UI with your software, even if it's
commercial and you charge money for your software. Inter UI can also be used
on the web by either hosting the font files yourself or by including this CSS:
</p>
<code>@import url('https://rsms.me/inter/inter-ui.css');</code>
<p>Use the following CSS rules to specify the Inter UI family:</p>
<code>font-family: 'Inter UI', sans-serif;</code>
<h2><a id="usage" href="#usage">How do I use it?</a></h2>
<p>
Using the font is as easy as
<a class="download-link" href="https://github.com/rsms/inter/releases/latest/">download &amp; installing</a> locally on your computer.
</p>
<p>
You're free to bundle copies of Inter UI with your software, even if it's
commercial and you charge money for your software. Inter UI can also be used
on the web by either hosting the font files yourself or by including this CSS:
</p>
<code>@import url('https://rsms.me/inter/inter-ui.css');</code>
<p>Use the following CSS rules to specify the Inter UI family:</p>
<code>font-family: 'Inter UI', sans-serif;</code>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2><a href="{{url_root}}dynmetrics/">Dynamic Metrics</a></h2>
<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.
<a href="{{url_root}}dynmetrics/">Learn about Dynamic Metrics —></a>
</p>
<h2><a id="free" href="#free">How much does it cost?</a></h2>
<p>
Inter UI is a <a href="https://github.com/rsms/inter">free and open source</a> font family. You are free to use this font in almost any way imaginable.
Refer to the <a href="https://choosealicense.com/licenses/ofl-1.1/">SIL Open Font License 1.1</a> for exact details on what the conditions and restrictions are.
</p>
<p>&nbsp;</p>
</div></div>
<h2><a id="free" href="#free">How much does it cost?</a></h2>
<p>
Inter UI is a <a href="https://github.com/rsms/inter">free and open source</a> font family. You are free to use this font in almost any way imaginable.
Refer to the <a href="https://choosealicense.com/licenses/ofl-1.1/">SIL Open Font License 1.1</a> for exact details on what the conditions and restrictions are.
</p>
<div class="row"><div>
<p>
There are currently four <a id="weights" href="#weights">weights</a>
</p>
<img src="res/weights-and-styles.svg" style="opacity:0.76;width:100%;display:block;margin:2em 0 3em 0">
<h2><a id="features" href="#features">Features</a></h2>
<boxes>
<box>
<h3>Contextual alternates (<q title='OpenType feature ID'>calt</q>)</h3>
<tablex><t>
<h><in>Disabled</in><to></to><out>Enabled</out></h>
<r><in>12<em>:</em>34, FE<em></em>X</in><to></to><out>12:34, FE—X</out></r>
<r><in>4<em>.</em>2</in><to></to><out>4.2</out></r>
<r><in>SFO <em>-></em> STO</in><to></to><out>SFO -> STO</out></r>
<r><in>IIA <em>—></em> OGG</in><to></to><out>IIA —> OGG</out></r>
<r><in>M<em>@</em>N m@n</in><to></to><out>M@N m@n</out></r>
</t></tablex>
</box>
</div></div>
<box>
<h3>Tabular numbers (<q title='OpenType feature ID'>tnum</q>)</h3>
<tablex><t>
<h><in>Disabled</in><to></to><out>Enabled</out></h>
<r><in><em>1</em>23456<em>7</em>890</in><to></to><out class="tnum">1234567890</out></r>
<r><in>1131711<em>&nbsp;</em></in><to></to><out class="tnum">1131711<em>&nbsp;</em></out></r>
<r><in>0040900<em>&nbsp;</em></in><to></to><out class="tnum">0040900<em>&nbsp;</em></out></r>
<r><in>11:31,711<em>&nbsp;</em></in><to></to><out class="tnum">11:31,711<em>&nbsp;</em></out></r>
<r><in>00:40.900<em>&nbsp;</em></in><to></to><out class="tnum">00:40.900<em>&nbsp;</em></out></r>
</t></tablex>
</box>
<div class="row"><div>
<p>
There are currently four <a id="weights" href="#weights">weights</a>
</p>
<img src="res/weights-and-styles.svg" style="opacity:0.76;width:100%;display:block;margin:2em 0 3em 0">
<h2><a id="features" href="#features">Features</a></h2>
<boxes>
<box>
<h3>Contextual alternates (<q title='OpenType feature ID'>calt</q>)</h3>
<tablex><t>
<h><in>Disabled</in><to></to><out>Enabled</out></h>
<r><in>12<em>:</em>34, FE<em></em>X</in><to></to><out>12:34, FE—X</out></r>
<r><in>4<em>.</em>2</in><to></to><out>4.2</out></r>
<r><in>SFO <em>-></em> STO</in><to></to><out>SFO -> STO</out></r>
<r><in>IIA <em>—></em> OGG</in><to></to><out>IIA —> OGG</out></r>
<r><in>M<em>@</em>N m@n</in><to></to><out>M@N m@n</out></r>
</t></tablex>
</box>
<box>
<h3>Slashed zero (<q title='OpenType feature ID'>zero</q>)</h3>
<tablex><t>
<h><in>Disabled</in><to></to><out>Enabled</out></h>
<r><in><em>0</em>123</in><to></to><out class="zero">0123</out></r>
</t></tablex>
</box>
<box>
<h3>Tabular numbers (<q title='OpenType feature ID'>tnum</q>)</h3>
<tablex><t>
<h><in>Disabled</in><to></to><out>Enabled</out></h>
<r><in><em>1</em>23456<em>7</em>890</in><to></to><out class="tnum">1234567890</out></r>
<r><in>1131711<em>&nbsp;</em></in><to></to><out class="tnum">1131711<em>&nbsp;</em></out></r>
<r><in>0040900<em>&nbsp;</em></in><to></to><out class="tnum">0040900<em>&nbsp;</em></out></r>
<r><in>11:31,711<em>&nbsp;</em></in><to></to><out class="tnum">11:31,711<em>&nbsp;</em></out></r>
<r><in>00:40.900<em>&nbsp;</em></in><to></to><out class="tnum">00:40.900<em>&nbsp;</em></out></r>
</t></tablex>
</box>
<box>
<h3>Fractions (<q title='OpenType feature ID'>frac</q>)</h3>
<tablex><t>
<h><in>Disabled</in><to></to><out>Enabled</out></h>
<r>
<in><em>1/3</em> <em>22/9</em> <em>3/4/5</em></in>
<to></to><out class="frac">1/3 22/9 3/4/5</out>
</r>
</t></tablex>
</box>
<box>
<h3>Slashed zero (<q title='OpenType feature ID'>zero</q>)</h3>
<tablex><t>
<h><in>Disabled</in><to></to><out>Enabled</out></h>
<r><in><em>0</em>123</in><to></to><out class="zero">0123</out></r>
</t></tablex>
</box>
<box>
<h3>Stylistic set 1: Alternate digits (<q title='OpenType feature ID'>ss01</q>)</h3>
<tablex><t>
<h><in>Disabled</in><to></to><out>Enabled</out></h>
<r>
<in><em>1</em>23<em>4</em>5<em>6</em>78<em>9</em>0</in>
<to></to><out class="ss01">1234567890</out>
</r>
<r><in><em>1</em></in><to></to><out class="ss01">1</out></r>
<r><in><em>4</em></in><to></to><out class="ss01">4</out></r>
<r><in><em>6</em></in><to></to><out class="ss01">6</out></r>
<r><in><em>9</em></in><to></to><out class="ss01">9</out></r>
</t></tablex>
</box>
<box>
<h3>Fractions (<q title='OpenType feature ID'>frac</q>)</h3>
<tablex><t>
<h><in>Disabled</in><to></to><out>Enabled</out></h>
<r>
<in><em>1/3</em> <em>22/9</em> <em>3/4/5</em></in>
<to></to><out class="frac">1/3 22/9 3/4/5</out>
</r>
</t></tablex>
</box>
<box>
<h3>Case alternates (<q title='OpenType feature ID'>case</q>)</h3>
<tablex><t>
<h><in>Disabled</in><to></to><out>Enabled</out></h>
<r>
<in><em>(</em>Hello<em>)</em> <em>[</em>World<em>]</em> <em>{</em>9000<em>}</em></in>
<to></to><out class="case">(Hello) [World] {9000}</out>
</r>
<r><in>SCHOOL <em>@</em> RUN</in><to></to><out class="case">SCHOOL @ RUN</out></r>
<r><in>3 <em>+</em> 9 <em>=</em> 12 <em>*</em> 1</in><to></to><out class="case">3 + 9 = 12 * 1</out></r>
<r><in><em>*</em> <em>+</em> <em>÷</em> <em>±</em> <em>×</em> <em>=</em> <em></em> <em></em></in><to></to><out class="case">* + ÷ ± × = ≠ •</out></r>
<r><in><em></em> <em></em> <em></em> <em></em> <em></em> <em>-</em> <em></em> <em></em> <em>:</em></in><to></to><out class="case">→ ← ⟶ ⟵ - — :</out></r>
</t></tablex>
</box>
<box>
<h3>Stylistic set 1: Alternate digits (<q title='OpenType feature ID'>ss01</q>)</h3>
<tablex><t>
<h><in>Disabled</in><to></to><out>Enabled</out></h>
<r>
<in><em>1</em>23<em>4</em>5<em>6</em>78<em>9</em>0</in>
<to></to><out class="ss01">1234567890</out>
</r>
<r><in><em>1</em></in><to></to><out class="ss01">1</out></r>
<r><in><em>4</em></in><to></to><out class="ss01">4</out></r>
<r><in><em>6</em></in><to></to><out class="ss01">6</out></r>
<r><in><em>9</em></in><to></to><out class="ss01">9</out></r>
</t></tablex>
</box>
</boxes>
<box>
<h3>Case alternates (<q title='OpenType feature ID'>case</q>)</h3>
<tablex><t>
<h><in>Disabled</in><to></to><out>Enabled</out></h>
<r>
<in><em>(</em>Hello<em>)</em> <em>[</em>World<em>]</em> <em>{</em>9000<em>}</em></in>
<to></to><out class="case">(Hello) [World] {9000}</out>
</r>
<r><in>SCHOOL <em>@</em> RUN</in><to></to><out class="case">SCHOOL @ RUN</out></r>
<r><in>3 <em>+</em> 9 <em>=</em> 12 <em>*</em> 1</in><to></to><out class="case">3 + 9 = 12 * 1</out></r>
<r><in><em>*</em> <em>+</em> <em>÷</em> <em>±</em> <em>×</em> <em>=</em> <em></em> <em></em></in><to></to><out class="case">* + ÷ ± × = ≠ •</out></r>
<r><in><em></em> <em></em> <em></em> <em></em> <em></em> <em>-</em> <em></em> <em></em> <em>:</em></in><to></to><out class="case">→ ← ⟶ ⟵ - — :</out></r>
</t></tablex>
</box>
<p>
Also includes some
Localized Forms (<q title='OpenType feature ID'>locl</q>),
Numerators (<q title='OpenType feature ID'>numr</q>) and
Denominators (<q title='OpenType feature ID'>dnom</q>).
</p>
</boxes>
<p>&nbsp;</p>
<p>
Also includes some
Localized Forms (<q title='OpenType feature ID'>locl</q>),
Numerators (<q title='OpenType feature ID'>numr</q>) and
Denominators (<q title='OpenType feature ID'>dnom</q>).
</p>
<h2 class="banner"><a href="glyphs/">Browse all glyphs -></a></h2>
</div></div>
<p>&nbsp;</p>
<div class="row-divider"></div>
<h2 class="banner"><a href="glyphs/">Browse all glyphs -></a></h2>
</div></div>
<div class="row"><div>
<h2><a id="story" href="#story">The story behind Inter UI</a></h2>
<p>
Inter UI started out in late 2016 as an experiment to build a perfectly
pixel-fitting font at a specific small size (11px.) The idea was that
by crafting a font in a particular way, with a particular coordinate system
(Units Per EM), and for a particular target rasterization size (11), it would
be possible to get the best of both sharpness and readability.
</p>
<p>
However after a few months of using an early version of Inter UI, it dawned
on everyone exposed to the test that this approach had some serious real-world
problems. Most notably that it was really hard to read longer text. Because of
the pixel-aligning nature of that approach, the font took an almost
<a href="https://www.figma.com/file/HPqDViSCB8fAWuxaV2ousFMv">mono-spaced appearance</a>,
making it really easy to read numbers, punctuation and very short
words, but eye-straining to read anything longer.
</p>
<p>
The project was rebooted with a different approach, sticking with the
specific UPM, but crafting glyphs and kerning in a way that made for
more variation in the rhythm and smoother vertical and horizontal stems.
As Inter UI was being developed, it was tested on an internal version of
<a href="https://www.figma.com/">Figma</a>—where the author of Inter UI works as a designer—and slowly improved upon based on experience and feedback.
</p>
<div class="row-divider"></div>
<p>&nbsp;</p>
<div class="row"><div>
<h2><a id="story" href="#story">The story behind Inter UI</a></h2>
<p>
Inter UI started out in late 2016 as an experiment to build a perfectly
pixel-fitting font at a specific small size (11px.) The idea was that
by crafting a font in a particular way, with a particular coordinate system
(Units Per EM), and for a particular target rasterization size (11), it would
be possible to get the best of both sharpness and readability.
</p>
<p>
However after a few months of using an early version of Inter UI, it dawned
on everyone exposed to the test that this approach had some serious real-world
problems. Most notably that it was really hard to read longer text. Because of
the pixel-aligning nature of that approach, the font took an almost
<a href="https://www.figma.com/file/HPqDViSCB8fAWuxaV2ousFMv">mono-spaced appearance</a>,
making it really easy to read numbers, punctuation and very short
words, but eye-straining to read anything longer.
</p>
<p>
The project was rebooted with a different approach, sticking with the
specific UPM, but crafting glyphs and kerning in a way that made for
more variation in the rhythm and smoother vertical and horizontal stems.
As Inter UI was being developed, it was tested on an internal version of
<a href="https://www.figma.com/">Figma</a>—where the author of Inter UI works as a designer—and slowly improved upon based on experience and feedback.
</p>
<h2><a id="status" href="#status">Current status &amp; usability</a></h2>
<p>
Inter UI works great for English-language text, and pretty well for other
Latin and Cyrillic languages. There's still a lot of work to be done, and
<a href="https://github.com/rsms/inter/blob/master/CONTRIBUTING.md">contributions are warmly welcomed</a>. The playground contains <a href="lab/?sample=Body%20text%201&size=16">a lot of samples</a>, including some common <a href="lab/?sample=Kerning%20body%20multi-lang&size=16">non English-language words in the playground.</a>
</p>
<p>&nbsp;</p>
<p>
Please refer to the <a href="glyphs/">glyph repertoire</a>
for an overview of currently-available glyphs and their quality.
</p>
<h2><a id="status" href="#status">Current status &amp; usability</a></h2>
<p>
Inter UI works great for English-language text, and pretty well for other
Latin and Cyrillic languages. There's still a lot of work to be done, and
<a href="https://github.com/rsms/inter/blob/master/CONTRIBUTING.md">contributions are warmly welcomed</a>. The playground contains <a href="lab/?sample=Body%20text%201&size=16">a lot of samples</a>, including some common <a href="lab/?sample=Kerning%20body%20multi-lang&size=16">non English-language words in the playground.</a>
</p>
<p>&nbsp;</p>
<p>
Please refer to the <a href="glyphs/">glyph repertoire</a>
for an overview of currently-available glyphs and their quality.
</p>
<h2><a id="faq" href="#faq">FAQ</a></h2>
<ul class="faq">
<p>&nbsp;</p>
<li class="q" id="faq-using-features">
How do I enable and disable font features?
</li>
<li class="a">
In web browsers you'll want to use
<a href="https://developer.mozilla.org/en-US/docs/Web/CSS/font-feature-settings"><q>font-feature-settings</q></a>.
In Figma you can access features via the
<a href="https://help.figma.com/text/opentype-features">Advanced Typography panel.</a>
In Illustrator, Photoshop and friends, you can access features via the
<a href="https://helpx.adobe.com/illustrator/using/special-characters.html#opentype_panel_overview">Characters and OpenType panels.</a>
Sketch doesn't provide a UI for configuring font features, but there's
<a href="https://sketchtalk.io/discussion/comment/1478/#Comment_1478">a workaround using macOS's native font UI.</a>
</li>
<h2><a id="faq" href="#faq">FAQ</a></h2>
<ul class="faq">
<li class="q" id="faq-unhinted-vs-hinted">
What is the difference between "unhinted" and "hinted" font files?
</li>
<li class="a">
The font files in the "hinted" folders have additional data in them
for assisting
<a href="https://en.wikipedia.org/wiki/ClearType">ClearType</a>,
the text rasterizer used by Microsoft Windows (and some Linux distributions.)
You want to use the "hinted" fonts only if you are targeting Windows users
<em>and</em> prefer the different look of these "hinted" fonts.
Additionally, hinting data makes the font files larger, so if you are
using Inter UI on websites, the extra size of these files is another
consideration to make.
<a href="https://www.typotheque.com/articles/hinting">
This article explains hinting at a greater length.</a>
</li>
<li class="q" id="faq-using-features">
How do I enable and disable font features?
</li>
<li class="a">
In web browsers you'll want to use
<a href="https://developer.mozilla.org/en-US/docs/Web/CSS/font-feature-settings"><q>font-feature-settings</q></a>.
In Figma you can access features via the
<a href="https://help.figma.com/text/opentype-features">Advanced Typography panel.</a>
In Illustrator, Photoshop and friends, you can access features via the
<a href="https://helpx.adobe.com/illustrator/using/special-characters.html#opentype_panel_overview">Characters and OpenType panels.</a>
Sketch doesn't provide a UI for configuring font features, but there's
<a href="https://sketchtalk.io/discussion/comment/1478/#Comment_1478">a workaround using macOS's native font UI.</a>
</li>
<li class="q" id="faq-unhinted-vs-hinted">
What is the difference between "unhinted" and "hinted" font files?
</li>
<li class="a">
The font files in the "hinted" folders have additional data in them
for assisting
<a href="https://en.wikipedia.org/wiki/ClearType">ClearType</a>,
the text rasterizer used by Microsoft Windows (and some Linux distributions.)
You want to use the "hinted" fonts only if you are targeting Windows users
<em>and</em> prefer the different look of these "hinted" fonts.
Additionally, hinting data makes the font files larger, so if you are
using Inter UI on websites, the extra size of these files is another
consideration to make.
<a href="https://www.typotheque.com/articles/hinting">
This article explains hinting at a greater length.</a>
</li>
<li class="q" id="faq-cdn">
How reliable are the fonts served from rsms.me/inter? Is it on a CDN?
</li>
<li class="a">
rsms.me/inter is backed by GitHub's server network and distributed
globally on the CloudFlare CDN, making usage of
<q>https://rsms.me/inter/inter-ui.css</q> and associated font
files very reliable and fast throughout the world.
</li>
<li class="q" id="faq-cdn">
How reliable are the fonts served from rsms.me/inter? Is it on a CDN?
</li>
<li class="a">
rsms.me/inter is backed by GitHub's server network and distributed
globally on the CloudFlare CDN, making usage of
<q>https://rsms.me/inter/inter-ui.css</q> and associated font
files very reliable and fast throughout the world.
</li>
<li class="q" id="faq-contribute">
Can I help with improving Inter UI?
</li>
<li class="a">
Yes you can! Inter UI is an open-source project, meaning the source
code—or "source design" if you will—that is used to build the font files
<a href="https://github.com/rsms/inter">are freely available</a> to improve upon.
Font making requires a fair bit of technical work and
depending on what you'd like to do, some things might be more fun
depending on your technical skills.
The <a href="https://github.com/rsms/inter/blob/master/CONTRIBUTING.md">"Contributing" document</a> is a great place to start. The document outlines where
you can have the biggest impact, how things are setup and how to get
started.
</li>
<li class="q" id="faq-contribute">
Can I help with improving Inter UI?
</li>
<li class="a">
Yes you can! Inter UI is an open-source project, meaning the source
code—or "source design" if you will—that is used to build the font files
<a href="https://github.com/rsms/inter">are freely available</a> to improve upon.
Font making requires a fair bit of technical work and
depending on what you'd like to do, some things might be more fun
depending on your technical skills.
The <a href="https://github.com/rsms/inter/blob/master/CONTRIBUTING.md">"Contributing" document</a> is a great place to start. The document outlines where
you can have the biggest impact, how things are setup and how to get
started.
</li>
<li class="q" id="faq-start-date">
This website claims work started in 2016, but the git repository's log says it started later?
</li>
<li class="a">
Inter UI was developed in an a private, internal git repository
starting in November 2016, prior to being published on August 22, 2017.
Between November 2016 and August 2017, there were
<num>2&#x2006;990&#x2006;150</num> line edits made across 247 versions.
The reason the public GitHub repository does not reflect this is the
fact that the project was initially only internal at the company where
the author works and had some sensitive information "checked in",
like AWS server details and internal author identity in
all commit messages. Maybe one day we can write an elaborate git
filter-branch program and convert the filter the old repository to make
it public, but what would be the point of that?&nbsp; :—)
</li>
<li class="q" id="faq-start-date">
This website claims work started in 2016, but the git repository's log says it started later?
</li>
<li class="a">
Inter UI was developed in an a private, internal git repository
starting in November 2016, prior to being published on August 22, 2017.
Between November 2016 and August 2017, there were
<num>2&#x2006;990&#x2006;150</num> line edits made across 247 versions.
The reason the public GitHub repository does not reflect this is the
fact that the project was initially only internal at the company where
the author works and had some sensitive information "checked in",
like AWS server details and internal author identity in
all commit messages. Maybe one day we can write an elaborate git
filter-branch program and convert the filter the old repository to make
it public, but what would be the point of that?&nbsp; :—)
</li>
<li class="q" id="faq-contact">
I've made a cool thing that uses Inter UI, can I share it with you?
&nbsp;<dem>or</dem>
</li>
<li class="q">
I have a different question
</li>
<li class="a">
Reach out on <a href="https://twitter.com/rsms">Twitter (@rsms)</a> or over <a href="mailto:rasmus@notion.se">email</a>
</li>
<li class="q" id="faq-contact">
I've made a cool thing that uses Inter UI, can I share it with you?
&nbsp;<dem>or</dem>
</li>
<li class="q">
I have a different question
</li>
<li class="a">
Reach out on <a href="https://twitter.com/rsms">Twitter (@rsms)</a> or over <a href="mailto:rasmus@notion.se">email</a>
</li>
</ul>
</ul>
</div></div>
</div></div>
<div class="row"><div>
<a href="https://twitter.com/rsms" class="plain">@rsms</a>
</div></div>
<div class="row"><div>
<a href="https://twitter.com/rsms" class="plain">@rsms</a>
</div></div>
<script src="index.js?v=2"></script>
<script>
(function(){
<script>(function(){
// FAQ anchors
var av = document.querySelectorAll('ul.faq > li.q'), a, i, e, id, tn
for (i = 0; i < av.length; ++i) {
e = av[i]
tn = document.createTextNode('Q  ')
e.insertBefore(tn, e.firstChild)
id = e.id
if (id) {
a = document.createElement('a')
// a.id = id
a.href = '#' + id
a.className = 'plain'
a.innerHTML = e.innerHTML
e.innerText = ''
e.appendChild(a)
}
}
av = document.querySelectorAll('ul.faq > li.a')
for (i = 0; i < av.length; ++i) {
e = av[i]
tn = document.createTextNode('A  ')
e.insertBefore(tn, e.firstChild)
}
// FAQ anchors
var av = document.querySelectorAll('ul.faq > li.q'), a, i, e, id, tn
for (i = 0; i < av.length; ++i) {
e = av[i]
tn = document.createTextNode('Q  ')
e.insertBefore(tn, e.firstChild)
id = e.id
if (id) {
a = document.createElement('a')
// a.id = id
a.href = '#' + id
a.className = 'plain'
a.innerHTML = e.innerHTML
e.innerText = ''
e.appendChild(a)
}
}
av = document.querySelectorAll('ul.faq > li.a')
for (i = 0; i < av.length; ++i) {
e = av[i]
tn = document.createTextNode('A  ')
e.insertBefore(tn, e.firstChild)
}
})();
</script>
</body>
</html>
})();</script>

View file

@ -1,138 +0,0 @@
var isMac = false
function $$(query, el) {
return [].slice.call((el || document).querySelectorAll(query))
}
function $(query, el) {
return (el || document).querySelector(query)
}
// fetchjson(url string, cb (err Error, d Object)->nil)
//
var fetchjson = (
typeof window.fetch == 'function' ? (
function _fetchjson(url, cb) {
return window.fetch(url)
.then(function(r) { return r.json() })
.then(function(data) { cb(null, data) })
.catch(cb)
}
) :
function _fetchjson(url, cb) {
var r = new XMLHttpRequest()
r.addEventListener("load", function(){
try {
cb(null, JSON.parse(r.responseText))
} catch (err) {
cb(err)
}
})
r.open("GET", url)
r.send()
}
)
;(function(){
"use strict";
// anim.min.js
var anim=function(h){h=function(a,e,f,b){var g,d,c=[],j=function(a){
if(a=c.shift())a[1]?h.apply(this,a).anim(j):0<a[0]?setTimeout(j,1E3*a[0]):(a[0](),j())};
a.charAt&&(a=document.getElementById(a));if(0<a||!a)e={},f=0,j(c=[[a||0]]);
q(e,{padding:0,margin:0,border:"Width"},[l,m,n,p]);q(e,{borderRadius:"Radius"},[l+p,l+m,n+m,n+p]);++r;
for(g in e)d=e[g],!d.to&&0!==d.to&&(d=e[g]={to:d}),h.defs(d,a,g,b);h.iter(e,1E3*f,j);
return{anim:function(){c.push([].slice.call(arguments));return this}}};
var l="Top", m="Right",n="Bottom",p="Left",r=1,q=function(a,e,f,b,g,d,c){for(b in a)if(b in e){c=a[b];
for(g=0;d=f[g];g++)a[b.replace(e[b],"")+d+(e[b]||"")]={to:0===c.to?c.to:c.to||c,fr:c.fr,e:c.e};
delete a[b]}},s=function(w,a){return w["r"+a]||w["webkitR"+a]||w["mozR"+a]||w["msR"+a]||w["oR"+a]}(
window,"equestAnimationFrame");h.defs=function(a,e,f,b,g){g=e.style;a.a=f;a.n=e;a.s=f in g?g:e;
a.e=a.e||b;a.fr=a.fr||(0===a.fr?0:a.s==e?e[f]:(window.getComputedStyle?getComputedStyle(e, null)
:e.currentStyle)[f]);a.u=(/\d(\D+)$/.exec(a.to)||/\d(\D+)$/.exec(a.fr)||[0,0])[1];a.fn=/color/i.test(f)?
h.fx.color:h.fx[f]||h.fx._;a.mx="anim_"+f;e[a.mx]=a.mxv=r;e[a.mx]!=a.mxv&&(a.mxv=null)};h.iter=function(a,e,f){
var b,g,d,c,h,k=+new Date+e;b=function(){g=k-(new Date).getTime();if(50>g){
for(d in a)d=a[d],d.p=1,d.fn(d,d.n,d.to,d.fr,d.a,d.e);f&&f()}else{g/=e;for(d in a){d=a[d];
if(d.n[d.mx]!=d.mxv)return;h=d.e;c=g;"lin"==h?c=1-c:"ease"==h?(c=2*(0.5-c),c=1-(c*c*c-3*c+2)/4):
"ease-in"==h?(c= 1-c,c*=c*c):c=1-c*c*c;d.p=c;d.fn(d,d.n,d.to,d.fr,d.a,d.e)}s?s(b):setTimeout(b,20)}};
b()};h.fx={_:function(a,e,f,b,g){b=parseFloat(b)||0;f=parseFloat(f)||0;a.s[g]=(1<=a.p?f:a.p*(f-b)+b)+a.u},
width:function(a,e,f,b,g,d){0<=a._fr||(a._fr=!isNaN(b=parseFloat(b))?b:"width"==g?e.clientWidth:e.clientHeight);
h.fx._(a,e,f,a._fr,g,d)},opacity:function(a,e,f,b,g){if(isNaN(b=b||a._fr))b=e.style,b.zoom=1,
b=a._fr=(/alpha\(opacity=(\d+)\b/i.exec(b.filter)||{})[1]/100||1;b*=1;f=a.p*(f-b)+b;e=e.style;g in e?e[g]= f:
e.filter=1<=f?"":"alpha("+g+"="+Math.round(100*f)+")"},color:function(a,e,f,b,g,d,c,j){
a.ok||(f=a.to=h.toRGBA(f),b=a.fr=h.toRGBA(b),0==f[3]&&(f=[].concat(b),f[3]=0),0==b[3]&&
(b=[].concat(f),b[3]=0),a.ok=1);j=[0,0,0,a.p*(f[3]-b[3])+1*b[3]];for(c=2;0<=c;c--)j[c]=Math.round(
a.p*(f[c]-b[c])+1*b[c]);(1<=j[3]||h.rgbaIE)&&j.pop();try{a.s[g]=(3<j.length?"rgba(":"rgb(")+j.join(",")+")"
}catch(k){h.rgbaIE=1}}};h.fx.height=h.fx.width;
h.RGBA=/#(.)(.)(.)\b|#(..)(..)(..)\b|(\d+)%,(\d+)%,(\d+)%(?:,([\d\.]+))?|(\d+),(\d+),(\d+)(?:,([\d\.]+))?\b/;
h.toRGBA=function(a,e){e=[0,0,0,0];a.replace(/\s/g,"").replace(h.RGBA,function(a,b,g,d,c,h,k,l,m,n,p,q,r,s,t){
k=[b+b||c,g+g||h,d+d||k];b=[l,m,n];for(a=0;3>a;a++)k[a]=parseInt(k[a],16),b[a]=Math.round(2.55*b[a]);
e=[k[0]||b[0]||q||0,k[1]||b[1]||r||0,k[2]||b[2]||s||0,p||t||1]});return e};return h}();
if (!window.MSStream &&
/mac|ipad|iphone|ipod/i.test(navigator.userAgent))
{
isMac = true
document.body.classList.add('mac_or_ios')
if (navigator.userAgent.indexOf('Safari') != -1) {
document.body.classList.add('safari')
}
}
// timeNow() :float
var timeNow = (
window.performance !== undefined && window.performance.now ? function() {
return window.performance.now()
} : Date.now ? function() {
return Date.now()
} : function() {
return (new Date()).getTime()
}
)
// download-link
fetchjson('/inter/info.json', function(err, data) {
if (err) { throw err }
var ids = Object.keys(data)
var regularId = ids[0]
ids.forEach(function(id){
if (id.indexOf('Inter UI Regular:') == 0) {
regularId = id
}
})
if (ids.length == 0) {
console.error('failed to find Inter UI Regular in info.json', data)
return
}
var regular = data[regularId]
// console.log('info.json:', regular)
if (regular.names && regular.names.version) {
var v = regular.names.version
var p = v.indexOf(';')
if (p != -1) {
v = v.substr(0, p)
}
var directDownloadURL =
'https://github.com/rsms/inter/releases/download/v' + v +
'/Inter-UI-' + v + '.zip'
var av = document.querySelectorAll('a.download-link'), i, e
for (i = 0; i < av.length; ++i) {
e = av[i]
e.href = directDownloadURL
}
}
})
// Google Analytics
;(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-105091131-2', 'auto');
ga('send', 'pageview');
})();

View file

@ -6,8 +6,8 @@ body {
font: 15px/22px 'Inter UI', system-ui, sans-serif;
font-size: 15px;
line-height:1.4;
/*letter-spacing: 0.009em;*/
line-height: 1.5;
letter-spacing: -0.002em;
font-weight: 400;
padding-bottom: 30px;
@ -83,11 +83,11 @@ q:after {
content: "";
}
kbd {
-moz-font-feature-settings: 'kern' 1, 'case' 1;
-ms-font-feature-settings: 'kern' 1, 'case' 1;
-o-font-feature-settings: 'kern' 1, 'case' 1;
-moz-font-feature-settings: 'kern' 1, 'case' 1;
-ms-font-feature-settings: 'kern' 1, 'case' 1;
-o-font-feature-settings: 'kern' 1, 'case' 1;
-webkit-font-feature-settings: 'kern' 1, 'case' 1;
font-feature-settings: 'kern' 1, 'case' 1;
font-feature-settings: 'kern' 1, 'case' 1;
border: 1px solid rgba(0,0,0,0.18);
border-radius: 3px;
padding:0.1em 0.2em;
@ -98,14 +98,20 @@ dem { /* de-emphasize */
opacity: 0.7;
}
num { /* number */
-moz-font-feature-settings: 'calt' 1, 'ss01' 1;
-ms-font-feature-settings: 'calt' 1, 'ss01' 1;
-o-font-feature-settings: 'calt' 1, 'ss01' 1;
/*-moz-font-feature-settings: 'calt' 1, 'ss01' 1;
-ms-font-feature-settings: 'calt' 1, 'ss01' 1;
-o-font-feature-settings: 'calt' 1, 'ss01' 1;
-webkit-font-feature-settings: 'calt' 1, 'ss01' 1;
font-feature-settings: 'calt' 1, 'ss01' 1;
font-feature-settings: 'calt' 1, 'ss01' 1;*/
letter-spacing:0.02em;
white-space: pre;
}
small {
font-size: 11px;
letter-spacing: 0.013em;
}
h1, h2, h3 {
font-weight: 500;
-webkit-font-smoothing: antialiased;
@ -176,11 +182,32 @@ h1 > a, h2 > a, h3 > a {
display: flex;
justify-content: center;
}
.row > * {
width:100%;
max-width: 888px;
flex: 1 0 100%;
.row > * {
width:100%;
max-width: 888px;
flex: 1 0 100%;
}
.row .learn-more {
margin-top: 2em;
text-align: center;
font-size: 11px;
letter-spacing: 0.007em;
}
.row .learn-more a {
color: rgba(0,0,0,0.4);
text-decoration-color: rgba(0, 0, 0, 0);
}
.row .learn-more a:hover {
color: inherit;
}
.row.full-width {
padding: 50px 0;
justify-content: flex-start;
}
.row.full-width > * {
max-width: initial;
}
.row-divider {
margin:0 auto;
@ -228,77 +255,6 @@ h1 > a, h2 > a, h3 > a {
opacity: 1;
}
/* narrow windows */
@media only screen and (max-width: 565px) {
.row.menu ul {
justify-content: space-between;
}
.row.menu ul li {
margin-right: 15px;
}
.row.menu ul li:last-child {
margin-right: 0;
}
.row.menu ul li.home {
/*color: red;
clear: both;*/
/*display: block;*/
text-align:center;
margin:0 0 -12px 0;
width: 100%;
}
.row.menu ul li.home > a {
border-bottom: none;
padding: 0 1em;
margin: 0.5em 0;
line-height:34px;
border-radius: 90px;
/*color: white;
background-color: rgba(3, 102, 214, 1);*/
}
.row.menu ul li.home > a:hover {
color: white;
background-color: #222;
}
}
/* small devices (<= iPhone 6+) */
@media only screen and (max-device-width: 414px) {
body {
font-size: 14px;
line-height: 20px;
}
.row {
padding-left: 20px;
padding-right: 20px;
}
.row.menu ul {
margin-left: 20px;
margin-right: 20px;
}
}
/* small devices (<= iPhone 5) */
@media only screen and (max-device-width: 320px) {
.row.menu {
font-size:13px;
}
.row.menu ul {
margin-left: 0;
margin-right: 0;
}
.row.menu ul li {
flex: 1 0 auto;
text-align: center;
border-right: 1px solid rgba(0,0,0,0.1);
margin-left:0;
margin-right:0;
}
.row.menu ul li:last-child {
border-right: none;
}
}
.row.white {
background: white;
@ -346,13 +302,9 @@ a > img {
}
.sample-images {}
.sample-images > img, .sample-images > svg {
.sample-images img, .sample-images svg {
display: block;
margin:100px 0;
width:100%;
}
.sample-images > img:first-child, .sample-images > svg:first-child {
margin-top:50px;
width: 100%;
}
@ -493,16 +445,16 @@ boxes {
}
box {
overflow: auto;
max-width:100%;
flex: 1 1 0;
min-width: 280px;
max-width: 100%;
display: flex;
flex-direction: column;
background: white;
padding:2em;
padding: 2em;
border-radius: 3px;
margin-right:1em;
margin-bottom:1em;
flex: 1 1 10%;
/*width:220px;*/
}
body.safari box {
/* Fix for broken flex wrap in safari */
@ -514,3 +466,85 @@ box:first-child {
box h3 {
margin-bottom:0.8em;
}
/* ------------------------------------------------------ */
/* narrow windows */
@media only screen and (max-width: 565px) {
.row.menu ul {
justify-content: space-between;
}
.row.menu ul li {
margin-right: 15px;
}
.row.menu ul li:last-child {
margin-right: 0;
}
.row.menu ul li.home {
/*color: red;
clear: both;*/
/*display: block;*/
text-align:center;
margin:0 0 -12px 0;
width: 100%;
}
.row.menu ul li.home > a {
border-bottom: none;
padding: 0 1em;
margin: 0.5em 0;
line-height:34px;
border-radius: 90px;
/*color: white;
background-color: rgba(3, 102, 214, 1);*/
}
.row.menu ul li.home > a:hover {
color: white;
background-color: #222;
}
}
/* small devices (<= iPhone 6+) */
@media only screen and (max-device-width: 414px) {
box { padding: 1em; }
box tablex r { font-size: 0.9em; }
body {
font-size: 14px;
line-height: 20px;
}
.row {
padding-left: 20px;
padding-right: 20px;
}
.row.menu ul {
margin-left: 20px;
margin-right: 20px;
}
}
/* small devices (<= iPhone 5) */
@media only screen and (max-device-width: 320px) {
box {
font-size: 0.8em;
min-width: 240px;
}
/*.row.menu {
font-size:13px;
}
.row.menu ul {
margin-left: 0;
margin-right: 0;
}
.row.menu ul li {
flex: 1 0 auto;
text-align: center;
border-right: 1px solid rgba(0,0,0,0.1);
margin-left:0;
margin-right:0;
}
.row.menu ul li:last-child {
border-right: none;
}*/
}

74
docs/res/base.js Normal file
View file

@ -0,0 +1,74 @@
function $$(query, el) {
return [].slice.call((el || document).querySelectorAll(query))
}
function $(query, el) {
return (el || document).querySelector(query)
}
// fetchjson(url string) :Promise<Object>
//
var fetchjson = (
typeof window.fetch == 'function' ? (
function _fetchjson(url, cb) {
return window.fetch(url).then(function(r) { return r.json() })
}
) :
function _fetchjson(url, cb) {
return new Promise(function(resolve, reject) {
var r = new XMLHttpRequest()
r.addEventListener("load", function(){
try {
resolve(JSON.parse(r.responseText))
} catch (err) {
reject(err)
}
})
r.addEventListener("error", function(ev) {
reject(ev.error || ev || new Error('network error'))
})
r.open("GET", url)
r.send()
})
}
)
// timeNow() :float
//
var timeNow = (
window.performance !== undefined && window.performance.now ? function() {
return window.performance.now()
} : Date.now ? function() {
return Date.now()
} : function() {
return (new Date()).getTime()
}
)
// Mac or not? Maybe even a buggy Safari?
var isMac = false
if (!window.MSStream &&
/mac|ipad|iphone|ipod/i.test(navigator.userAgent))
{
isMac = true
if (navigator.userAgent.indexOf('Safari') != -1 &&
navigator.userAgent.indexOf('Chrome') == -1)
{
document.body.classList.add('safari')
}
}
// Google Analytics
// ;(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
// (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
// m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
// })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
// ga('create', 'UA-105091131-2', 'auto');
// ga('send', 'pageview');
window.dataLayer = window.dataLayer || [];
window.dataLayer.push(['js', new Date()])
window.dataLayer.push(['config', 'UA-105091131-2'])

View file

@ -1,11 +1,14 @@
// requires index.js
function passThrough(v) { return v }
function Binding(name){
this.name = name
this.value = undefined
this.inputs = []
this.listeners = []
this.formatter = undefined
this.parser = undefined
this.formatter = passThrough
}
@ -22,7 +25,7 @@ Binding.prototype.addInput = function(el) {
if (this.value === undefined) {
this.value = el.value
} else {
input.el.value = this.value
input.el.value = this.formatter(this.value)
}
el.addEventListener('input', _onInput, {passive:true})
}
@ -39,8 +42,8 @@ Binding.prototype.addListener = function(listener) {
Binding.prototype.setValue = function(nextval, origin) {
// console.log('Binding.setValue nextval:', nextval, {origin})
var prevval = this.value
if (this.formatter) {
nextval = this.formatter(nextval, prevval)
if (this.parser) {
nextval = this.parser(nextval, prevval)
}
if (this.value === nextval) {
return
@ -49,7 +52,7 @@ Binding.prototype.setValue = function(nextval, origin) {
this.value = nextval
this.inputs.forEach(function(input) {
if (input.el !== origin) {
input.el.value = nextval
input.el.value = binding.formatter(nextval)
}
})
this.listeners.forEach(function(listener) {
@ -106,6 +109,11 @@ Bindings.prototype.setValue = function(name, value) {
binding.setValue(value)
}
Bindings.prototype.setFormatter = function(name, formatter) {
var binding = this.getBinding(name)
binding.formatter = formatter || passThrough
}
Bindings.prototype.value = function(name, defaultValue) {
var binding = this.bindings[name]
@ -125,11 +133,11 @@ function fmt_int(nextval, prevval) {
// configure is convenience function for setting value, adding a
// listener and associating a formatter with a binding.
// listener and associating a parser with a binding.
// If a listener and a value is provided, the value is set and the listener
// is immediately invoked.
//
Bindings.prototype.configure = function(name, value, formatter, listener) {
Bindings.prototype.configure = function(name, value, parser, listener) {
var binding = this.getBinding(name)
if (listener) {
binding.addListener(listener)
@ -137,23 +145,23 @@ Bindings.prototype.configure = function(name, value, formatter, listener) {
if (value !== undefined && value !== null) {
binding.setValue(value)
}
if (formatter) {
if (typeof formatter == 'string') {
switch (formatter) {
if (parser) {
if (typeof parser == 'string') {
switch (parser) {
case 'number':
case 'float':
formatter = fmt_float; break;
parser = fmt_float; break;
case 'int':
case 'integer':
formatter = fmt_int; break;
parser = fmt_int; break;
default:
throw new Error('unknown formatter "' + formatter + '"')
throw new Error('unknown parser "' + parser + '"')
}
} else if (typeof formatter != 'function') {
throw new Error('formatter should be a string or function')
} else if (typeof parser != 'function') {
throw new Error('parser should be a string or function')
}
binding.formatter = formatter
binding.parser = parser
}
}

View file

Before

Width:  |  Height:  |  Size: 700 B

After

Width:  |  Height:  |  Size: 700 B

Before After
Before After

239
docs/res/graphplot.js Normal file
View file

@ -0,0 +1,239 @@
function GraphPlot(canvas) {
this.canvas = canvas
const g = canvas.getContext('2d')
if (g == null) {
throw new Error('failed to acquire 2d context')
}
this.width = 0 // dp
this.height = 0 // dp
this.widthPx = 0 // px
this.heightPx = 0 // px
this.pixelRatio = 1
this.g = g
this.dataSegments = []
this.axes = {
x0: .5, // % from left to x=0
y0: .5, // % from top to y=0
scalex: 40, // pixels from x=0 to x=1
scaley: 40, // pixels from y=0 to y=1
negativeX: true,
}
if (!this.autosize()) {
this.setSize(256, 256)
}
}
GraphPlot.prototype.autosize = function() {
try {
this.canvas.width = null
this.canvas.height = null
this.canvas.style.width = null
this.canvas.style.height = null
var cs = window.getComputedStyle(this.canvas)
var width = parseFloat(cs.width)
var height = parseFloat(cs.height)
this.setSize(width, height)
return true
} catch (err) {
if (typeof console != 'undefined' && console.warn) {
console.warn('GraphPlot.autosize failed: ' + err)
}
}
return false
}
// setOrigin sets the origin of axis x and y
// The values should be in the range [0-1] and maps to the extremes
// of the canvas.
//
GraphPlot.prototype.setOrigin = function(x, y) {
var p = this
p.axes.x0 = x
p.axes.y0 = y
}
// setScale sets the value scale for x and y axis.
// The values should be provided as display points.
//
GraphPlot.prototype.setScale = function(x, y) {
var p = this
if (y === undefined) {
y = x
}
p.axes.scalex = x
p.axes.scaley = y
}
// setSize sets the size of canvas in display points
//
GraphPlot.prototype.setSize = function(width, height) {
var p = this
p.width = width
p.height = height
const el = p.canvas, g = p.g
p.pixelRatio = window.devicePixelRatio || 1
if (p.pixelRatio != 1) {
el.width = p.widthPx = width * p.pixelRatio
el.height = p.heightPx = height * p.pixelRatio
g.scale(p.pixelRatio, p.pixelRatio)
} else {
el.width = p.widthPx = width
el.height = p.heightPx = height
g.scale(1, 1)
}
el.style.width = `${width}px`
el.style.height = `${height}px`
}
GraphPlot.prototype.renderAxes = function() {
var p = this
, g = p.g
, x0 = Math.round(p.axes.x0 * p.widthPx) / p.pixelRatio
, y0 = Math.round(p.axes.y0 * p.heightPx) / p.pixelRatio
g.beginPath()
g.strokeStyle = "rgb(0, 0, 0, 0.2)"
if (y0 > 0 && y0 < p.width) {
g.moveTo(0, y0); g.lineTo(p.width, y0) // X axis
}
if (x0 > 0 && x0 < p.height) {
g.moveTo(x0, 0); g.lineTo(x0, p.height) // Y axis
}
g.stroke()
}
// plotf plots an arbitrary function on the graph
//
GraphPlot.prototype.plotf = function(f, color) {
var p = this
, g = p.g
, w = p.width
, h = p.height
, x0 = p.axes.x0 * p.width
, y0 = p.axes.y0 * p.height
, x = 0
, y = 0
, dx = 4 / p.pixelRatio // smaller means finer curves and more CPU
, scalex = p.axes.scalex * w
, scaley = p.axes.scaley * h
, iMax = Math.round((w - x0) / dx)
, iMin = p.axes.negativeX ? Math.round(-x0 / dx) : 0
g.beginPath()
g.lineWidth = 1
g.strokeStyle = color || "rgb(0, 0, 0, 0.8)"
for (var i = iMin; i <= iMax; i++) {
x = dx * i
y = f(x / scalex) * scaley
if (i == iMin) {
g.moveTo(x0 + x, y0 - y)
} else {
g.lineTo(x0 + x, y0 - y)
}
}
g.stroke()
}
// plotLines draws straight lines between a collection of points
//
GraphPlot.prototype.plotLine = function(points, color) {
var p = this
, g = p.g
, x0 = p.axes.x0 * p.width
, y0 = p.axes.y0 * p.height
, x = 0
, y = 0
, scalex = p.axes.scalex * p.width
, scaley = p.axes.scaley * p.height
, pt
g.beginPath()
g.lineWidth = 1
g.strokeStyle = color || "rgb(0, 0, 0, 0.8)"
var i = 0
for (; i < points.length; i++) {
pt = points[i]
x = pt[0] * scalex
y = pt[1] * scaley
if (i == 0) {
g.moveTo(x0 + x, y0 - y)
} else {
g.lineTo(x0 + x, y0 - y)
}
}
g.stroke()
}
// plotPoints draws points
//
GraphPlot.prototype.plotPoints = function(points, color) {
var p = this
, g = p.g
, x0 = p.axes.x0 * p.width
, y0 = p.axes.y0 * p.height
, x = 0
, y = 0
, scalex = p.axes.scalex * p.width
, scaley = p.axes.scaley * p.height
, pt
, i = 0
g.fillStyle = color || "rgb(0, 0, 0, 0.8)"
for (; i < points.length; i++) {
pt = points[i]
x = x0 + pt[0] * scalex
y = y0 - pt[1] * scaley
g.beginPath()
g.arc(x, y, 3, 0, Math.PI + (Math.PI * 2) / 2, false)
g.fill()
}
}
GraphPlot.prototype.clear = function() {
var p = this
p.g.clearRect(0, 0, p.width, p.height)
p.renderAxes()
}
GraphPlot.prototype.renderDemo = function() {
var p = this
, g = p.g
, dpscale = p.pixelRatio
, w = p.widthPx
, h = p.heightPx
p.clear()
p.plotf(
function(x) { return Math.sin(x) },
'blue'
)
p.plotf(
function(x) { return Math.cos(3*x) },
'hotpink'
)
// var scale = p.height / 4
// g.moveTo(0, scale)
// var i, sine, lines = 200, frag = p.width / lines
// for (i = 0; i < lines; i++) {
// sine = Math.sin(i / scale * 2) * scale
// g.lineTo(i * frag, -sine + scale)
// }
// g.stroke()
}

243
docs/samples/index.css Normal file
View file

@ -0,0 +1,243 @@
body {
padding-bottom: 0;
background: white;
}
.row.footer h2 {
margin:0;
text-align:center;
}
livesample {
display: block;
color: #111;
outline: none;
padding-left: 20px;
border-left: 2px solid transparent;
margin-left:-22px;
margin-top: 1em;
margin-bottom: 1.6em;
}
livesample:hover {
/*color: rgb(3, 102, 214);*/
border-left-color: rgb(3, 102, 214);
}
livesample:focus {
border-left-color: #eee;
}
livesample > p {
margin-top: 0;
}
livesample.s1 {
padding-left: 16px;
letter-spacing: -0.01em;
font-size: 5em;
font-weight: 600;
line-height: 1.1;
margin-top: 0;
margin-bottom: 0.3em;
}
livesample.s2 {
max-width: 400px;
font-size: 1em;
}
livesample.s3 {
font-size: 13px;
line-height: 18px;
}
livesample.s3 b, livesample.s3 strong {
font-weight:500;
color: black;
}
livesample.col3 {
-moz-column-width: 20em;
-moz-columns: 20em;
-webkit-columns: 20em;
columns: 20em;
-moz-column-gap: 2em;
-webkit-column-gap: 2em;
column-gap: 2em;
}
livesample.col2 {
-moz-column-count: 2;
-webkit-column-count: 2;
column-count: 2;
}
.font-style-regular { font-weight:400 !important; font-style:normal !important; }
.font-style-italic { font-weight:400 !important; font-style:italic !important; }
.font-style-medium { font-weight:500 !important; font-style:normal !important; }
.font-style-medium-italic { font-weight:500 !important; font-style:italic !important; }
.font-style-bold { font-weight:700 !important; font-style:normal !important; }
.font-style-bold-italic { font-weight:700 !important; font-style:italic !important; }
.font-style-black { font-weight:900 !important; font-style:normal !important; }
.font-style-black-italic { font-weight:900 !important; font-style:italic !important; }
div.live {
margin-top:1em;
margin-bottom:100px;
padding-bottom:20px;
border-bottom: 1px solid #ddd;
}
div.live .learn-more {
margin-top:40px;
user-select: none;
}
div.controls {
position: absolute;
right: 0;
top: 150px;
width: 250px;
padding: 10px 0;
/*background:#eee;*/
opacity:0.3;
transition: 90ms opacity cubic-bezier(0.25, 0.47, 0.44, 0.93);
/*border:1px solid #bbb;*/
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
border-right:none;
display: flex;
flex-direction: column;
overflow: hidden;
font-size: 13px;
}
div.controls:hover {
opacity:1;
background:#f5f5f5;
border-color: transparent;
}
div.controls .control {
display: flex;
justify-content: space-between;
align-items: center;
overflow: hidden;
min-height: 30px;
margin: 0 16px;
}
div.controls .control > * {
flex: 1 1 auto;
margin:0;
margin-right: 16px;
box-sizing: border-box;
}
div.controls .control > :last-child {
margin-right: 0;
}
div.controls .control > select {
min-width: 6em;
align-items: center;
justify-content: center;
}
div.controls .control > input,
div.controls .control > select {
width: 0;
outline: none;
}
div.controls .control > input[type="number"],
div.controls .control > input[type="text"] {
background: none;
border: none;
padding: 4px 0;
font-size: inherit;
/*border-radius: 2px;*/
}
div.controls .control > input[type="number"] {
max-width: 48px;
text-align: right;
-moz-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
-ms-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
-o-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
-webkit-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
}
div.controls .control > input[type=number]::-webkit-inner-spin-button,
div.controls .control > input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
div.controls .control > input[type="range"] {
/*max-width: 80%;*/
flex: 1 1 auto;
display: block;
}
div.controls .control > img.icon,
div.controls .control > label {
font-family: georgia, serif;
font-style: italic;
color: black;
width: 16px;
height: 16px;
flex: 0 0 auto;
margin-right: 16px;
opacity: 0.6;
}
div.controls canvas {
height: 200px;
}
div.controls .control.info,
div.controls canvas {
transition: 390ms opacity cubic-bezier(0.25, 0.47, 0.44, 0.93);
opacity: 0;
}
div.controls:hover .control.info,
div.controls:hover canvas {
opacity: 1;
}
/* narrow windows */
@media only screen and (max-width: 1200px) {
div.controls {
width: 210px;
font-size: 12px;
}
}
@media only screen and (max-width: 1024px) {
div.controls {
width: 140px;
font-size: 11px;
}
div.controls canvas {
display: none;
}
div.controls .control.info {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
div.controls .control > input[type="range"] {
width: 0;
flex: 0 1 0%;
display: none;
}
div.controls .control > input[type="number"] {
max-width: 100%;
flex: 1 1 auto;
}
}
@media only screen and (max-width: 740px) {
livesample.s1 {
font-size:4.5em;
}
div.controls {
display: none;
}
}
@media only screen and (max-width: 565px) {
livesample.s1 {
font-size:4em;
}
}
@media only screen and (max-width: 414px) {
livesample.s1 {
font-size:3.4em;
}
}
.sample-images img, .sample-images svg {
margin: 100px 0;
}
.sample-images > img:first-child, .sample-images > svg:first-child {
margin-top:50px;
}

View file

@ -1,300 +1,73 @@
<!DOCTYPE HTML>
<html lang="en" prefix="og: http://ogp.me/ns#">
<head>
<meta charset="utf-8">
<title>Inter UI font family</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta property="og:title" content="Inter UI font family">
<meta property="twitter:title" content="Inter UI font family">
<meta property="description" content="Inter UI is a new typeface optimized for computer user interfaces">
<meta property="og:description" content="Inter UI is a new typeface optimized for computer user interfaces">
<meta property="twitter:description" content="Inter UI is a new typeface optimized for computer user interfaces">
<meta property="twitter:card" content="summary">
<meta property="twitter:site" content="@rsms">
<meta property="twitter:creator" content="@rsms">
<meta property="og:image" content="https://rsms.me/inter/res/poster.png">
<meta property="twitter:image" content="https://rsms.me/inter/res/poster.png">
<meta property="fb:app_id" content="38027689216">
<meta property="og:url" content="https://rsms.me/inter/">
<meta property="og:site_name" content="rsms.me">
<meta property="og:type" content="product">
<meta property="og:locale" content="en_US" />
<meta name="format-detection" content="telephone=no">
<link rel="icon" type="image/png" href="../favicon.png" />
<link href="../inter-ui.css?v=2.5" rel="stylesheet">
<link href="../index.css?v=5" rel="stylesheet">
<style type="text/css">
body {
padding-bottom: 0;
background: white;
}
---
layout: default
title: Samples
---
{%
.row.footer h2 {
margin:0;
text-align:center;
}
capture url_root
%}{% if site.safe == false %}/{% else %}/inter/{% endif
%}{%
endcapture %}{%
/*.row.menu {
background: white;
}*/
for file in site.static_files %}{%
assign _path = file.path | remove_first: "/inter" %}{%
if _path == "/samples/index.css" %}{%
assign index_css_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
elsif _path == "/res/bindings.js" %}{%
assign bindings_js_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
elsif _path == "/res/graphplot.js" %}{%
assign graphplot_js_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
endif %}{%
endfor
livesample {
display: block;
color: #111;
outline: none;
padding-left: 20px;
border-left: 2px solid transparent;
margin-left:-22px;
margin-top: 1em;
margin-bottom: 1.6em;
}
livesample:hover {
/*color: rgb(3, 102, 214);*/
border-left-color: rgb(3, 102, 214);
}
livesample:focus {
border-left-color: #eee;
}
livesample > p {
margin-top: 0;
}
livesample.s1 {
padding-left: 16px;
letter-spacing: -0.005em;
font-size: 5em;
font-weight: 600;
line-height: 1.1;
margin-top: 0;
margin-bottom: 0.3em;
}
livesample.s2 {
max-width: 400px;
font-size: 1em;
}
livesample.s3 {
font-size: 13px;
line-height: 18px;
}
livesample.s3 b, livesample.s3 strong {
font-weight:500;
color: black;
}
%}
<link rel="stylesheet" href="index.css?v={{ index_css_v }}">
<script src="{{url_root}}res/bindings.js?v={{ bindings_js_v }}"></script>
<script src="{{url_root}}res/graphplot.js?v={{ graphplot_js_v }}"></script>
livesample.col3 {
-moz-column-width: 20em;
-moz-columns: 20em;
-webkit-columns: 20em;
columns: 20em;
<div class="row"><div>
<div class="live">
-moz-column-gap: 2em;
-webkit-column-gap: 2em;
column-gap: 2em;
}
livesample.col2 {
-moz-column-count: 2;
-webkit-column-count: 2;
column-count: 2;
}
.font-style-regular { font-weight:400 !important; font-style:normal !important; }
.font-style-italic { font-weight:400 !important; font-style:italic !important; }
.font-style-medium { font-weight:500 !important; font-style:normal !important; }
.font-style-medium-italic { font-weight:500 !important; font-style:italic !important; }
.font-style-bold { font-weight:700 !important; font-style:normal !important; }
.font-style-bold-italic { font-weight:700 !important; font-style:italic !important; }
.font-style-black { font-weight:900 !important; font-style:normal !important; }
.font-style-black-italic { font-weight:900 !important; font-style:italic !important; }
div.live {
margin-top:1em;
margin-bottom:100px;
padding-bottom:100px;
border-bottom: 1px solid #ddd;
}
div.controls {
position: absolute;
right: 0;
top: 150px;
width: 220px;
padding: 10px 16px;
/*background:#eee;*/
opacity:0.3;
border:1px solid #bbb;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
border-right:none;
display: flex;
flex-direction: column;
overflow: hidden;
}
div.controls:hover {
opacity:1;
background:#f5f5f5;
border-color: transparent;
}
div.controls .control {
display: flex;
justify-content: space-between;
align-items: center;
overflow: hidden;
height:30px;
}
div.controls .control > * {
/*max-width: 50%;*/
flex: 1 1 auto;
margin:0;
margin-right: 16px;
box-sizing: border-box;
}
div.controls .control > :last-child {
margin-right: 0;
}
div.controls .control > select {
min-width: 6em;
align-items: center;
justify-content: center;
}
div.controls .control > input,
div.controls .control > select {
width: 0;
outline: none;
}
div.controls .control > input[type="number"],
div.controls .control > input[type="text"] {
background: none;
border: none;
padding: 4px 0;
font-size: 13px;
/*border-radius: 2px;*/
}
div.controls .control > input[type="number"] {
max-width: 60px;
text-align: right;
-moz-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
-ms-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
-o-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
-webkit-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
}
div.controls .control > input[type="range"] {
/*max-width: 80%;*/
flex: 1 1 auto;
display: block;
}
div.controls .control > img.icon {
width: 16px;
height: 16px;
flex: 0 0 auto;
margin-right: 16px;
opacity: 0.8;
}
/*div.controls .control > input.foo {
background-color: hotpink;
border:none;
border-radius: 90px;
}*/
/* narrow windows */
@media only screen and (max-width: 1200px) {
div.live div.controls {
width: 200px;
}
}
@media only screen and (max-width: 1024px) {
div.live div.controls {
width: 100px;
}
div.controls .control > input[type="range"] {
width: 0;
flex: 0 1 0%;
display: none;
}
div.controls .control > input[type="number"] {
max-width: 100%;
flex: 1 1 auto;
}
}
@media only screen and (max-width: 740px) {
livesample.s1 {
font-size:4.5em;
}
div.live div.controls {
display: none;
}
}
@media only screen and (max-width: 565px) {
livesample.s1 {
font-size:4em;
}
}
@media only screen and (max-width: 414px) {
livesample.s1 {
font-size:3.4em;
}
}
</style>
</head>
<body>
<div class="row menu">
<ul class="menu">
<li class="home"><a href="../">Inter UI</a></li>
<li><a class="download-link"
href="https://github.com/rsms/inter/releases/latest/"
>Download</a></li>
<li><a href="/inter/samples/" class="active">Samples</a></li>
<li><a href="../lab/">Playground</a></li>
<li><a href="https://github.com/rsms/inter/">Source</a></li>
</ul>
<div class="controls">
<div class="control">
<img title="Style" class="icon" src="icons/style.svg">
<select data-binding="style">
<option value="regular" default>Regular</option>
<option value="italic">Italic</option>
<option value="medium" default>Medium</option>
<option value="medium-italic">Medium Italic</option>
<option value="bold" default>Bold</option>
<option value="bold-italic">Bold Italic</option>
<option value="black" default>Black</option>
<option value="black-italic">Black Italic</option>
</select>
</div>
<div class="control">
<img title="Size" class="icon" src="icons/font-size.svg">
<input type="range" min="8" max="100" step="1" data-binding="font-size">
<input type="number" min="4" max="400" step="1" data-binding="font-size">
</div>
<div class="control">
<img title="Letter spacing in EM" class="icon" src="icons/letter-spacing.svg">
<input type="range" min="-0.05" max="0.06" step="0.001" data-binding="letter-spacing">
<input type="number" min="-0.15" max="1" step="0.001" data-binding="letter-spacing">
</div>
<canvas class="graphplot">Canvas not Supported</canvas>
<div class="control info">
<a href="{{url_root}}dynmetrics/">Learn about Dynamic Metrics</a>
</div>
</div>
<div class="row white"><div>
<div class="live">
<livesample contenteditable class="s1">
Fabulous typography encountering spring
</livesample>
<div class="controls">
<div class="control">
<img title="Style" class="icon" src="icons/style.svg">
<select data-binding="style">
<option value="regular" default>Regular</option>
<option value="italic">Italic</option>
<option value="medium" default>Medium</option>
<option value="medium-italic">Medium Italic</option>
<option value="bold" default>Bold</option>
<option value="bold-italic">Bold Italic</option>
<option value="black" default>Black</option>
<option value="black-italic">Black Italic</option>
</select>
</div>
<div class="control">
<img title="Size" class="icon" src="icons/font-size.svg">
<input type="range" min="8" max="100" step="1" data-binding="font-size">
<input type="number" min="4" max="400" step="1" data-binding="font-size">
</div>
<div class="control">
<img title="Letter spacing in EM" class="icon" src="icons/letter-spacing.svg">
<input type="range" min="-0.05" max="0.06" step="0.001" data-binding="letter-spacing">
<input type="number" min="-0.15" max="1" step="0.001" data-binding="letter-spacing">
</div>
<!-- <div class="control">
<img class="icon" src="icons/font-size.svg">
<input type="text" class="foo" data-binding="foo">
<input type="text" class="foo" data-binding="foo">
</div> -->
</div>
<livesample contenteditable class="s2">
The user interface (UI), in the industrial design field of human-computer
interaction, is the space where interactions between humans and machines occur.
</livesample>
<livesample contenteditable class="s1">
Fabulous typography encountering spring
</livesample>
<livesample contenteditable class="s2">
The user interface (UI), in the industrial design field of human-computer
interaction, is the space where interactions between humans and machines occur.
</livesample>
<livesample contenteditable class="s3 col3">
<livesample contenteditable class="s3 col3">
<p><b>Fire Island Beach</b> is a barrier of sand, stretching for twenty miles
along the south coast of Long Island, and separating the Great South Bay
from the Atlantic ocean.
@ -350,89 +123,67 @@ When the tide is on the right moon and the wind has blown a gale from
the southeast, the strand is entirely submerged, and people upon the
main shore three miles away can see the surf breaking over the Beach
hills.
</p><p>
Such a riot of sea and wind strews the whole extent of beach with
whatever has been lost or thrown overboard, or torn out of sunken ships.
Many a man has made a good weeks work in a single day by what he has
found while walking along the Beach when the surf was down.
</p><p>
“The Captain” knew all this and had patrolled that Beach scores of
times.
</p><p>
Ten years had passed since the first time which laid the habit of
wandering along the surf-shore apparently in search of whatever the sea
had cast up. Sometimes a spar, sometimes sheets of copper torn from a
wreck and carried by a high surf far along the strand, sometimes a
vessels gilded name, at other times only scattered drift-wood were the
rewards of these lonely walks.
</p>
</livesample>
</div>
</livesample>
<p class="learn-more">
&nbsp;
<!-- <a href="{{url_root}}dynmetrics/">Learn about Dynamic Metrics</a> -->
</p>
</div>
<p class="sample-images">
<img src="img/01.png" srcset="img/01@2x.png 2x" width="888">
<img src="img/02.png" srcset="img/02@2x.png 2x" width="888">
<!-- <img src="img/02.svg" width="888"> -->
<img src="img/03.png" srcset="img/03@2x.png 2x" width="888">
<img src="img/04.png" srcset="img/04@2x.png 2x" width="888">
<img src="img/05.png" srcset="img/05@2x.png 2x" width="888">
<img src="img/dark-phone.jpg" srcset="img/dark-phone@2x.jpg 2x" width="888">
<img src="img/06.png" srcset="img/06@2x.png 2x" width="888">
<img src="img/07.png" srcset="img/07@2x.png 2x" width="888">
<img src="img/08.png" srcset="img/08@2x.png 2x" width="888">
<img src="img/09.png" srcset="img/09@2x.png 2x" width="888">
<img src="img/10.png" srcset="img/10@2x.png 2x" width="888">
<img src="img/11.png" srcset="img/11@2x.png 2x" width="888">
<img src="img/12.png" srcset="img/12@2x.png 2x" width="888">
<img src="img/13.png" srcset="img/13@2x.png 2x" width="888">
<img src="img/14.png" srcset="img/14@2x.png 2x" width="888">
<img src="img/15.png" srcset="img/15@2x.png 2x" width="888">
</p>
<p style="text-align:center">
<a href="https://www.figma.com/file/WmU5NWr52bnUcqv5os0V4sWi/" class="plain">Open these samples in Figma</a>
</p>
</div></div>
<p class="sample-images">
<img src="img/01.png" srcset="img/01@2x.png 2x" width="888">
<img src="img/02.png" srcset="img/02@2x.png 2x" width="888">
<!-- <img src="img/02.svg" width="888"> -->
<img src="img/03.png" srcset="img/03@2x.png 2x" width="888">
<img src="img/04.png" srcset="img/04@2x.png 2x" width="888">
<img src="img/05.png" srcset="img/05@2x.png 2x" width="888">
<img src="img/dark-phone.jpg" srcset="img/dark-phone@2x.jpg 2x" width="888">
<img src="img/06.png" srcset="img/06@2x.png 2x" width="888">
<img src="img/07.png" srcset="img/07@2x.png 2x" width="888">
<img src="img/08.png" srcset="img/08@2x.png 2x" width="888">
<img src="img/09.png" srcset="img/09@2x.png 2x" width="888">
<img src="img/10.png" srcset="img/10@2x.png 2x" width="888">
<img src="img/11.png" srcset="img/11@2x.png 2x" width="888">
<img src="img/12.png" srcset="img/12@2x.png 2x" width="888">
<img src="img/13.png" srcset="img/13@2x.png 2x" width="888">
<img src="img/14.png" srcset="img/14@2x.png 2x" width="888">
<img src="img/15.png" srcset="img/15@2x.png 2x" width="888">
</p>
<p style="text-align:center">
<a
href="https://www.figma.com/file/WmU5NWr52bnUcqv5os0V4sWi/"
class="plain">Open these samples in Figma</a>
</p>
</div></div>
<script src="../index.js?v=2"></script>
<script src="bindings.js"></script>
<script type="text/javascript">(function(){
<script type="text/javascript">(function(){
// InterUIDynamicTracking takes the font size in points or pixels and returns
// the compensating tracking in EM.
// InterUIDynamicTracking produces tracking in EM for the given font size
//
function InterUIDynamicTracking(fontSize, weightClass) {
// if (!weightClass) { -- currently unused
// weightClass = 400
// }
//
// y = -0.01021241 + 0.3720623 * e ^ (-0.2808687 * x)
// [6-35] 0.05877 .. -0.0101309 (13==0; stops growing around 30-35)
// See https://gist.github.com/rsms/8efdbca5f8145a584ed08a7c3d6e5788
//
return -0.01021241 + 0.3720623 * Math.pow(Math.E, (-0.2808687 * fontSize))
// y = 0.025 - (ln(x) * 0.01)
// return 0.025 - Math.log(fontSize) * 0.01
var a = -0.0149, b = 0.298, c = -0.23;
return a + b * Math.pow(Math.E, (c * fontSize))
}
function InterUIDynamicLeading(fontSize, weightClass) {
var lineHeight = Math.round(fontSize * 1.4)
//
// TODO
//
// console.log(
// 'lineHeight:', lineHeight,
// `(${Math.round(fontSize * 1.45)})`,
// )
return lineHeight
// InterUIDynamicLineHeight produces the line height for the given font size
//
function InterUIDynamicLineHeight(fontSize, weightClass) {
var l = 1.4
return Math.round(fontSize * l)
}
var bindings = new Bindings()
var graph = new GraphPlot($('canvas.graphplot'))
graph.setOrigin(-0.2, 0.8)
graph.setScale(0.049, 5)
var s2 = $('livesample.s2')
@ -443,22 +194,39 @@ function updateWidth() {
s2.style.maxWidth = Math.round(w) + 'px'
}
function updateTracking() {
var fontSize = bindings.value('font-size', 0)
var letterSpacing = InterUIDynamicTracking(fontSize, 400)
bindings.setValue('letter-spacing', letterSpacing)
}
function updateGraph() {
graph.clear()
var fontSize = bindings.value('font-size', 0)
var letterSpacing = bindings.value('letter-spacing')
graph.plotf(function(x) {
return InterUIDynamicTracking(x, 400)
})
var graphedFontSize = Math.min(24, fontSize) // clamp to [-inf,24]
graph.plotPoints([[graphedFontSize, letterSpacing]], '#000')
}
bindings.configure('letter-spacing', 0, 'float', function (letterSpacing) {
s2.style.letterSpacing = letterSpacing + 'em'
updateWidth()
updateGraph()
})
bindings.setFormatter('letter-spacing', function(v) {
return v.toFixed(3)
})
bindings.configure('font-size', 18, 'int', function(fontSize, prevval) {
bindings.configure('font-size', 16, 'float', function(fontSize, prevval) {
s2.style.fontSize = fontSize + 'px'
updateWidth()
updateTracking()
var letterSpacing = InterUIDynamicTracking(fontSize, 400)
letterSpacing = parseFloat(letterSpacing.toFixed(3)) // lower precision
var lineHeight = InterUIDynamicLeading(fontSize, 400)
var lineHeight = InterUIDynamicLineHeight(fontSize, 400)
s2.style.lineHeight = lineHeight + 'px'
bindings.setValue('letter-spacing', letterSpacing)
})
bindings.configure('style', null, null, function (style) {
@ -478,8 +246,14 @@ bindings.configure('style', null, null, function (style) {
bindings.bindAllInputs('div.live .control input')
bindings.bindAllInputs('div.live .control select')
// resize canvas when window resizes
var resizeDebounceTimer = null
window.addEventListener('resize', function(){
clearTimeout(resizeDebounceTimer)
resizeDebounceTimer = setTimeout(function(){
graph.autosize()
updateGraph()
}, 500)
}, {passive:true, capture:false})
})();</script>
</body>
</html>
})();</script>

View file

@ -1,24 +0,0 @@
#!/bin/sh
set -e
cd "$(dirname "$0")"
if [ ! -s lab/fonts ]; then
ln -s ../../build/dist lab/fonts
fi
if (which caddy >/dev/null); then
caddy_args=(\
-host localhost \
"bind localhost" \
"mime .woff2 font/woff2" \
"mime .woff application/font-woff" \
)
caddy "${caddy_args[@]}"
elif (which servedir >/dev/null); then
servedir
else
echo "Can not find 'caddy' nor 'servedir' in PATH." >&2
echo "Install caddy from brew, apt or https://caddyserver.com/download"
echo "or install servedir with 'npm install -g secure-servedir'"
exit 1
fi

View file

@ -7,6 +7,7 @@ import os
import sys
import argparse
import json
import re
from base64 import b64encode
from fontTools import ttLib
@ -288,6 +289,13 @@ def genFontInfo(fontpath, outputType, withGlyphs=True):
if 'subfamilyName' in nameDict:
info['name'] += '-' + nameDict['subfamilyName'].replace(' ', '')
if 'version' in nameDict:
version = nameDict['version']
v = re.split(r'[\s;]+', version)
if v and len(v) > 0:
version = v[0]
info['version'] = version
if outputType is not OUTPUT_TYPE_GLYPHLIST:
if len(nameDict):
info['names'] = nameDict
@ -425,7 +433,7 @@ def main():
args = argparser.parse_args()
fonts = {}
fonts = []
outputType = OUTPUT_TYPE_COMPLETE
if args.asGlyphList:
outputType = OUTPUT_TYPE_GLYPHLIST
@ -437,7 +445,7 @@ def main():
# internal cache that mixes up values for different fonts.
reload(sstruct)
font = genFontInfo(fontpath, outputType=outputType, withGlyphs=args.withGlyphs)
fonts[font['id']] = font
fonts.append(font)
n += 1
ostream = sys.stdout
@ -447,6 +455,7 @@ def main():
if args.prettyJson:
json.dump(fonts, ostream, sort_keys=True, indent=2, separators=(',', ': '))
sys.stdout.write('\n')
else:
json.dump(fonts, ostream, separators=(',', ':'))