WIP WYSIWYG ~3D SVG editor.
at main 329 lines 6.6 kB view raw
1/* Global styles */ 2*, *::before, *::after { 3 box-sizing: border-box; 4 margin: 0; 5 line-height: calc(1em + 0.5rem); 6} 7 8body { 9 -webkit-font-smoothing: antialiased; 10} 11 12img, picture, video, canvas, svg { 13 display: block; 14 max-width: 100%; 15} 16 17input, button, textarea, select { 18 font: inherit; 19 border: none; 20} 21 22/* Presets */ 23:root { 24 --charcoal: #333; 25 --raisin: #534; 26 --faded-raisin: #5342; 27 --plum: #636; 28 --rose: #C25; 29 --orange: #E62; 30 --gold: #EA0; 31 --lemon: #ED0; 32 --peach: #FDB; 33 --lace: #FFF4E8; 34 --blueberry: #359; 35 --lime: #4A2; 36 --mint: #CFD; 37 38 --roundness: .5rem; 39} 40 41/* Fonts */ 42body { 43 font-family: "din-2014-rounded-variable", sans-serif; 44 font-variation-settings: "wght" 400; 45 color: var(--raisin); 46} 47 48/* Toolbar */ 49button { 50 width: 2rem; 51 height: 2rem; 52 border-radius: var(--roundness); 53 54 color: var(--raisin); 55 background: var(--lace); 56 box-shadow: 0 0 0 0.25rem transparent; 57 58 cursor: pointer; 59 font-size: 0; 60 transition: box-shadow 0.2s, background 0.2s; 61} 62 63button:first-letter { 64 font-size: 1.5rem; 65 line-height: 2rem; 66 font-variation-settings: "wght" 600; 67} 68 69button:hover { 70 background: var(--peach); 71 box-shadow: 0 1px 0.25rem 0 color-mix(in srgb, var(--raisin) 10%, transparent); 72} 73 74menu { 75 position: fixed; 76 left: 0; 77 height: 100vh; 78 padding-left: 1rem; 79 padding-top: 1rem; 80 display: flex; 81 flex-direction: column; 82 gap: .5em; 83} 84 85menu li { 86 list-style: none; 87} 88 89main { 90 width: 100vw; 91 height: 100vh; 92 93 display: grid; 94 grid-template-columns: 1fr 20rem; 95 grid-template-rows: 20rem 1fr; 96 grid-template-areas: 97 "canvas outliner" 98 "canvas properties"; 99} 100 101/* Canvas */ 102.canvas-container { 103 position: relative; 104 grid-area: canvas; 105} 106 107.canvas-layer { 108 position: absolute; 109 width: 100%; 110 height: 100%; 111 pointer-events: none; 112} 113 114#canvas { 115 pointer-events: auto; 116 z-index: 0; 117} 118 119#canvas { 120 cursor: grab; 121} 122 123#overlay ~ #canvas:active { 124 cursor: grabbing; 125} 126 127#canvas > * { 128 cursor: pointer; 129} 130 131/* Change to pointer when clicking on canvas would deselect elements */ 132#overlay:has(> *) ~ #canvas { 133 cursor: pointer; 134} 135 136#overlay { 137 opacity: 0.8; 138 z-index: 1; 139} 140 141/*#overlay:not(:empty) { 142 filter: url(#better-highlight); 143}*/ 144 145#ui { 146 z-index: 2; 147} 148 149#ui > *, #ui.active { 150 pointer-events: auto; 151 cursor: pointer; 152} 153 154/* Panels */ 155#properties, #outliner { 156 max-height: 100%; 157 overflow-y: scroll; 158 margin: 1rem; 159 padding: 1rem; 160 background: var(--lace); 161 color: var(--raisin); 162 border-radius: var(--roundness); 163 border: 2px solid var(--raisin); 164 box-shadow: .5px .5px 0 .5px var(--raisin); 165} 166 167#properties { 168 grid-area: properties; 169 margin-top: .5rem; 170} 171 172#outliner { 173 grid-area: outliner; 174 margin-bottom: .5rem; 175} 176 177/* Properties */ 178.prop-group { 179 padding: .5rem; 180 margin: .5rem; 181 border: 2px solid var(--faded-raisin); 182 border-radius: var(--roundness); 183} 184 185.prop { 186 display: flex; 187 flex-flow: row wrap; 188 align-items: center; 189 justify-content: space-between; 190} 191 192.prop h4 { 193 flex-basis: 100%; 194 text-align: center; 195 line-height: 1; 196 margin-top: .5rem; 197} 198 199.prop.vector label { 200 margin-right: 0 !important; 201} 202 203.prop.vector input + label { 204 margin-left: .75rem; 205} 206 207.prop input[type="number"] { 208 width: 1rem; 209 flex-grow: 10; 210} 211 212.prop input { 213 margin: .25rem 0; 214 padding: .125rem; 215 text-align: center; 216 max-width: 6rem; 217 border: 1px solid var(--raisin); 218 box-shadow: .5px .5px 0 .5px var(--raisin); 219 border-radius: calc( var(--roundness) / 2 ); 220} 221 222#properties label { 223 font-weight: bold; 224 font-size: 1em; 225 margin-right: .25rem; 226 flex-grow: 1; 227} 228 229#properties.hidden .prop-group, 230#properties .prop-group:not(:has(:not(.hidden))), 231#properties .hidden { 232 display: none; 233} 234 235/* Hide disabled optional properties */ 236#properties .prop.optional input[type="checkbox"]:not(:checked) + input { 237 display: none; 238} 239 240/* Outliner */ 241#outliner ul { 242 --color: #333; 243 padding-left: 0; 244} 245 246#outliner li { 247 list-style: none; 248 padding: .1rem .5rem; 249 padding-right: 0; 250 font-size: 1.1rem; 251} 252 253#outliner .name { 254 display: inline-block; 255 width: 100%; 256} 257 258#outliner li.selected { 259 background: var(--peach); 260 color: #111; 261 border-radius: var(--roundness); 262 263 & > .name { 264 font-weight: bold; 265 color: #000; 266 text-decoration: underline; 267 } 268} 269 270#outliner .icon { 271 display: inline-block; 272 width: 1rem; 273 height: 1rem; 274 background-color: var(--color); 275 vertical-align: middle; 276 margin-right: .25rem; 277 border-radius: .25rem; 278} 279 280/* Outliner icons */ 281/*#outliner .icon { 282 clip-path: circle(50%); 283} 284 285#outliner [data-type] > .name > .icon { 286 width: 32px; 287 height: 32px; 288 transform: scale(0.5); 289 margin: -8px; 290 margin-right: calc( .25rem - 8px ); 291} 292 293#outliner [data-type="Illustration"] > .name > .icon { 294 clip-path: path("M30.5 6.3c0-1.8.5-5.1-6.9-5.1S2.5.5 1.4 1.6 1 17.4.9 20C.8 33.8.8 30.8 29.4 30.9s.4-21.1 1-24.7zM3.8 3.7c7.1-.1 14.2 0 21.3.6 1.3 7.2 1.4 14.5.4 21.7-7.1-.1-14.2-.3-21.3-.4-.3-6.1-.4-20.7-.4-21.9zm9.3 16.4c-1 .1-2.3.6-3.3.2-1.7-.8-.5-2.5 0-3.6 1.4-2.6 2.4-5.4 3.6-8 0-1.5 2-2 2.8-.7 1.7 2.8 3.5 5.5 5.1 8.4 2.2 4.1-6.1 3.1-8.3 3.8z"); 295} 296 297#outliner [data-type="Cone"] > .name > .icon { 298 clip-path: path("M27.7,22.6c-3.4-5.9-6.4-11.9-9-18.2,0,0,0,0,0,0-.4-.9-.6-2.1-1.8-2.1-4.8-1.4-8.7,12.1-10.9,15.7-.4,2-3.8,4.7-1.8,6.5,3.9,3.3,25,5.9,23.5-1.9ZM10.1,16c1.6-3.6,3.3-7.4,5.8-10.5,2.2,5.2,4.6,10.2,7.3,15.1-4.8-1.3-10.1-1.7-14.9-.6.6-1.3,1.2-2.7,1.8-4Z"); 299} 300#outliner [data-type="Shape"] > .name > .icon { 301 clip-path: path("M26.58 5.2c-2.01-5-9.77-1.5-8.26 3.29-9.06 2.82.9 13.49-6.37 15.01 1.51-6.12-7.26-9.07-8.02-2.1-.24 2.47 1.45 4.4 4.36 4.16 9 .93 9.75-1.72 8.85-10.88-.25-2.54 1.82-4.02 3.15-3.98 2.39.69 8.54-.26 6.29-5.5zM6.61 22.66c-1.14-2.55 2.18-3.31 2.7-1.4.45 1.64-1.84 2.96-2.7 1.4zM24.54 7.08c.46 1.93-3.4 2.59-3.73.65-.41-2.39 2.91-4.06 3.73-.65z"); 302}*/ 303 304/* Footer */ 305/* Animation */ 306@keyframes toast { 307 0% { 308 transform: translateY(100%); 309 } 310 10%, 90% { 311 transform: translateY(0); 312 } 313 100% { 314 transform: translateY(100%); 315 } 316} 317footer { 318 display: inline-block; 319 position: fixed; 320 bottom: 0; 321 left: 0; 322 padding: .25rem; 323 background: var(--lace); 324 color: var(--raisin); 325 border-top-right-radius: .25rem; 326 animation: toast 5s; 327 animation-delay: 2s; 328 transform: translateY(100%); 329}