A world-class math input for the web
1html,
2body,
3#app {
4 width: 100%;
5 height: 100%;
6 margin: 0;
7 padding: 0;
8 overflow: hidden;
9}
10
11#app {
12 display: grid;
13 grid-template-columns: 1fr 1fr;
14 grid-template-rows: 1fr 1fr;
15 grid-template-areas:
16 "input-area parsed-area"
17 "tokens-area parsed-area";
18}
19
20#input-area,
21#tokens-area,
22#parsed-area,
23#parsed-diagram-area {
24 border: 1px solid black;
25 padding: 10px;
26 overflow: auto;
27}
28
29#input-area {
30 grid-area: input-area;
31 overflow: hidden;
32}
33#tokens-area {
34 grid-area: tokens-area;
35}
36#parsed-area {
37 grid-area: parsed-area;
38}
39#parsed-diagram-area {
40 grid-area: parsed-diagram-area;
41}
42
43.math {
44 font-family: Symbola, "Times New Roman", serif;
45 font-size: 24px;
46 font-weight: 400;
47 padding: 0.25em 0.5em;
48 /* font-size: 75px; */
49
50 display: inline-block;
51 border: 1px solid black;
52
53 /* No wrapping */
54 box-sizing: border-box;
55 white-space: nowrap;
56 max-width: 100%;
57 overflow-x: auto;
58}
59
60.strand > * {
61 margin: 0 0.08em;
62}
63
64.cursor {
65 margin: 0 -0.04em;
66 display: inline-block;
67 border-left: 1px solid black;
68 vertical-align: baseline;
69 animation: blink 1s steps(1) infinite;
70
71 /*
72 The cursor contains a zero-width space for styling purposes (so it has a natural character height but no width).
73 If users accidentally copy & pasate this character, it can be very confusing, so we disable selecting it.
74 */
75 user-select: none;
76}
77
78@keyframes blink {
79 0%,
80 50% {
81 border-left-color: black;
82 }
83 50.01%,
84 100% {
85 border-left-color: transparent;
86 }
87}
88
89.selected {
90 background-color: rgba(0, 120, 215, 0.3);
91}
92
93.fraction {
94 display: inline-block;
95 text-align: center;
96 font-size: 0.85em;
97 vertical-align: 0.33em; /* 4. Move the fraction up slightly relative to the surrounding text. This adjusts the fraction so that the fraction bar is inline with the center of the surrounding text rather than the surrounding text's baseline. */
98}
99
100.fraction .fraction .fraction {
101 font-size: 1em; /* Stop shrinking font size after third level */
102}
103
104.numerator {
105 display: block;
106 overflow: hidden; /* 3. When an element's overflow property is not "visible", its baseline becomes the bottom edge of the element rather than the baseline of the text within it. This is good because it aligns the center of the fraction (the bottom of the numerator) with the baseline of the surrounding text. */
107
108 /* Avoid clipping cursor on right edge of numerator due to overflow: hidden */
109 padding: 0 1px;
110 margin: 0 -1px;
111}
112
113.denominator {
114 display: block;
115 float: left; /* 1. This causes the denominator to be taken out of the text flow, making the baseline of the numerator align with the overall baseline. (This is then adjusted to center the fraction bar.) */
116 width: 100%; /* 2. Floating this element causes it to stop being full width, but we want it to be full width just like the numerator is so that centering the text works. */
117}
118
119.denominator::before {
120 user-select: none;
121 content: "";
122 display: block;
123 height: 0.06em;
124 background: currentColor;
125 width: 100%;
126 border-radius: 0.03em;
127}
128
129.numerator:empty::after,
130.denominator:empty::after {
131 display: inline-block;
132 content: "";
133 width: 0.6em;
134 height: 0.6em;
135 background: #ddd;
136}
137
138.subsup {
139 display: inline-block;
140 font-size: 0.6em;
141 vertical-align: 0.33em;
142}
143
144.subscript {
145 display: block;
146 float: left;
147 width: 100%;
148}
149
150.superscript {
151 display: block;
152 overflow: hidden;
153
154 padding: 0 1px;
155 margin: 0 -1px;
156}
157
158.radical {
159 display: inline-flex;
160 align-items: flex-start;
161 position: relative;
162}
163
164.radical-index {
165 font-size: 0.75em;
166}
167
168.radicand {
169 position: relative;
170 display: inline-block;
171 border-top: 0.1em solid currentColor;
172 border-left: 0.1em solid currentColor;
173}
174
175.radicand::before {
176 content: "";
177 position: absolute;
178 width: 0.35em;
179 height: 0.35em;
180 bottom: 0em;
181 left: -0.1em;
182 transform-origin: center center;
183 transform: translateX(-50%) translateY(-20%) rotate(-45deg);
184 border-left: 0.1em solid currentColor;
185 box-sizing: border-box;
186 font-size: 1em;
187}
188
189.matrix {
190 display: inline-table;
191 position: relative;
192 font-size: 0.9em;
193 text-align: center;
194 vertical-align: middle;
195}
196
197.matrix-square {
198 padding-left: 0.2em;
199 padding-right: 0.2em;
200}
201
202.matrix-square::before {
203 content: "";
204 position: absolute;
205 left: 0;
206 top: 0;
207 width: 0.25em;
208 height: 100%;
209 border-top: 0.1em solid currentColor;
210 border-left: 0.1em solid currentColor;
211 border-bottom: 0.1em solid currentColor;
212}
213
214.matrix-square::after {
215 content: " ";
216 position: absolute;
217 right: 0;
218 top: 0;
219 width: 0.25em;
220 height: 100%;
221 border-top: 0.1em solid currentColor;
222 border-right: 0.1em solid currentColor;
223 border-bottom: 0.1em solid currentColor;
224}