├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── dist ├── _redirects ├── index.html └── manifest.json ├── gulpfile.js ├── media ├── css-transform.gif └── css-transform.jpg ├── package-lock.json ├── package.json └── src ├── _redirects ├── css ├── app.css └── app.less ├── index.html ├── js └── app.js └── manifest.json /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: alterebro 2 | ko_fi: alterebro 3 | buy_me_a_coffee: alterebro 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .npm 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Jorge Moreno 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # css-transform › [css-transform.moro.es](https://css-transform.moro.es/) 2 | 3 | **CSS3 Transform Functions Playground**. Demo UI built with [Vue](https://vuejs.org/), [Gulp](https://gulpjs.com/) and [LESS](http://lesscss.org/). Deployment via [Netlify](https://www.netlify.com/) 4 | 5 | [![Netlify Status](https://api.netlify.com/api/v1/badges/61609638-1191-4dfa-ab28-53af3b7c17c0/deploy-status)](https://www.netlify.com/) 6 | 7 | [![CSS Transform](media/css-transform.gif)](https://css-transform.moro.es) 8 | 9 | --- 10 | 11 | ## Development 12 | 13 | ### — Install 14 | 15 | Clone or [download](https://github.com/alterebro/css-transform/archive/master.zip) the repository and install dependencies 16 | 17 | ```sh 18 | $ git clone https://github.com/alterebro/css-transform.git 19 | $ cd css-transform/ 20 | $ npm install 21 | ``` 22 | 23 | ### — Serve 24 | 25 | Start a local server, i.e the `SimpleHTTPServer` python module 26 | 27 | ```sh 28 | $ python -m SimpleHTTPServer 29 | 30 | # Source : http://0.0.0.0:8000/src/ 31 | # Compiled : http://0.0.0.0:8000/dist/ 32 | ``` 33 | 34 | ### — Build 35 | 36 | Using *gulp* to compile the project 37 | 38 | ```sh 39 | $ npm install gulp-cli -g # In case gulp isn't already installed 40 | $ gulp build 41 | ``` 42 | 43 | --- 44 | 45 | *Jorge Moreno — [@alterebro](https://twitter.com/alterebro)* 46 | -------------------------------------------------------------------------------- /dist/_redirects: -------------------------------------------------------------------------------- 1 | # Redirect default Netlify subdomain to primary domain 2 | https://css-transform.netlify.com/* https://css-transform.moro.es/:splat 301! 3 | -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | CSS Transform Functions Visualizer

CSS3 Transform

2D & 3D CSS Transform functions visualizer


×
Front
Back

Rotation (2D)

rotate() Rotates an element around a fixed point on the 2D plane.

The rotate() CSS function defines a transformation that rotates an element around a fixed point on the 2D plane, without deforming it. The amount of rotation created by rotate() is specified by an angle value expressed in degrees, gradians, radians, or turns. If positive, the movement will be clockwise; if negative, it will be counter-clockwise. (A rotation by 180° is called point reflection.)

The axis of rotation passes through an origin, defined by the transform-origin CSS property.

More info: developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotate


Rotation (3D)

rotateX() Rotates an element around the horizontal axis.

The rotateX() CSS function defines a transformation that rotates an element around the abscissa (horizontal axis) without deforming it. The amount of rotation created by rotateX() is specified by an angle value expressed in degrees, gradians, radians, or turns. If positive, the movement will be clockwise; if negative, it will be counter-clockwise.

The axis of rotation passes through an origin, defined by the transform-origin CSS property.

rotateX(a) is equivalent to rotate3d(1, 0, 0, a).

More info : developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotateX

rotateY() Rotates an element around the vertical axis.

The rotateY() CSS function defines a transformation that rotates an element around the ordinate (vertical axis) without deforming it. The amount of rotation created by rotateY() is specified by an angle value expressed in degrees, gradians, radians, or turns. If positive, the movement will be clockwise; if negative, it will be counter-clockwise.

The axis of rotation passes through an origin, defined by the transform-origin CSS property.

rotateY(a) is equivalent to rotate3d(0, 1, 0, a).

More info : developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotateY

rotateZ() Rotates an element around the z-axis.

The rotateZ() CSS function defines a transformation that rotates an element around the z-axis without deforming it.

The amount of rotation created by rotateZ() is specified by an angle value expressed in degrees, gradians, radians, or turns. If positive, the movement will be clockwise; if negative, it will be counter-clockwise.

The axis of rotation passes through an origin, defined by the transform-origin CSS property.

rotateZ(a) is equivalent to rotate(a) or rotate3d(0, 0, 1, a).

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotateZ


Perspective

perspective() Sets the distance between the user and the z=0 plane.

The perspective() CSS function defines a transformation that sets the distance between the user and the z=0 plane.

The perspective distance used by perspective() is specified by a length value (a number followed by a length unit: em, rem, px, pt, mm…), which represents the distance between the user and the z=0 plane. A positive value makes the element appear closer to the user, a negative value farther.

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/perspective


Transform Origin

transform-origin() Sets the origin for an element's transformations.

The transformation origin is the point around which a transformation is applied. For example, the transformation origin of the rotate() function is the center of rotation.

The transform-origin property may be specified using one, two, or three values, where each value represents an offset. Offsets that are not explicitly defined are reset to their corresponding initial values.

If two or more values are defined and either no value is a keyword, or the only used keyword is center, then the first value represents the horizontal offset and the second represents the vertical offset.

  • One-value syntax: The value must be a length, a percentage, or one of the keywords left, center, right, top, and bottom.
  • Two-value syntax: One value must be a length, a percentage, or one of the keywords left, center, and right. The other value must be a length, a percentage, or one of the keywords top, center, and bottom.
  • Three-value syntax: The first two values are the same as for the two-value syntax. The third value must be a length. It always represents the Z offset.

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin


Scaling (Resizing)

scale() Scales an element up or down on the 2D plane.

The scale() CSS function defines a transformation that resizes an element on the 2D plane. Because the amount of scaling is defined by a vector, it can resize the horizontal and vertical dimensions at different scales.

This scaling transformation is characterized by a two-dimensional vector. Its coordinates define how much scaling is done in each direction. If both coordinates are equal, the scaling is uniform (isotropic) and the aspect ratio of the element is preserved (this is a homothetic transformation).

When a coordinate value is outside the [-1, 1] range, the element grows along that dimension; when inside, it shrinks. If it is negative, the result a point reflection in that dimension. A value of 1 has no effect.

The scale() function only scales in 2D. To scale in 3D, use scale3d() instead.

The scale() function is specified with either one or two values, which represent the amount of scaling to be applied in each direction.

scale(sx)
 2 | scale(sx, sy)
 3 | /*
 4 | - sx : A number representing the abscissa of the scaling vector.
 5 | - sy : A number representing the ordinate of the scaling vector. If not defined, its default value is sx, resulting in a uniform scaling that preserves the element's aspect ratio.
 6 | */

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scale

scaleX() Scales an element up or down horizontally.

The scaleX() CSS function defines a transformation that resizes an element along the x-axis (horizontally).

It modifies the abscissa of each element point by a constant factor, except when the scale factor is 1, in which case the function is the identity transform. The scaling is not isotropic, and the angles of the element are not conserved. scaleX(-1) defines an axial symmetry, with a vertical axis passing through the origin (as specified by the transform-origin property).

scaleX(sx) is equivalent to scale(sx, 1) or scale3d(sx, 1, 1).

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scaleX

scaleY() Scales an element up or down vertically.

The scaleY() CSS function defines a transformation that resizes an element along the y-axis (vertically).

It modifies the ordinate of each element point by a constant factor, except when the scale factor is 1, in which case the function is the identity transform. The scaling is not isotropic, and the angles of the element are not conserved. scaleY(-1) defines an axial symmetry, with a horizontal axis passing through the origin (as specified by the transform-origin property).

scaleY(sy) is equivalent to scale(1, sy) or scale3d(1, sy, 1).

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scaleY


Translation (Moving)

translate() Translates an element on the 2D plane.

The translate() CSS function repositions an element in the horizontal and/or vertical directions.

This transformation is characterized by a two-dimensional vector. Its coordinates define how much the element moves in each direction.

The translate() function is specified as either one or two values.

translate(tx)
 7 | translate(tx, ty)
 8 | /*
 9 | - tx : Is a length value representing the abscissa (x-coordinate) of the translating vector.
10 | - ty : Is a length value representing the ordinate of the translating vector (or y-coordinate). If unspecified, its default value is 0. For example, translate(2) is equivalent to translate(2, 0).
11 | */

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translate

translateX() Translates an element horizontally.

The translateX() CSS function repositions an element horizontally on the 2D plane.

Syntax : translateX(t). (t is a length value representing the abscissa of the translating vector.)

translateX(tx) is equivalent to translate(tx, 0) or translate3d(tx, 0, 0).

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translateX

translateY() Translates an element vertically.

The translateY() CSS function repositions an element vertically on the 2D plane.

translateY(ty) is equivalent to translate(0, ty) or translate3d(0, ty, 0).

Syntax : translateY(t). (t is a length value representing the ordinate of the translating vector.)

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translateY


Skewing (Distortion)

skew() Skews an element on the 2D plane.

The skew() CSS function defines a transformation that skews an element on the 2D plane.

This transformation is a shear mapping (transvection) that distorts each point within an element by a certain angle in the horizontal and vertical directions. The coordinates of each point are modified by a value proportionate to the specified angle and the distance to the origin; thus, the farther from the origin a point is, the greater will be the value added it.

The skew() function is specified with either one or two values, which represent the amount of skewing to be applied in each direction.

skew(ax)
12 | skew(ax, ay)
13 | /*
14 | - ax : Is an angle value expressed in degrees, gradians, radians, or turns; representing the angle to use to distort the element along the abscissa.
15 | - ay : Is an angle value expressed in degrees, gradians, radians, or turns; representing the angle to use to distort the element along the ordinate. If not defined, its default value is 0, resulting in a purely horizontal skewing.
16 | */

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/skew

skewX() : Skews an element in the horizontal direction.

The skewX() CSS function defines a transformation that skews an element in the horizontal direction on the 2D plane.

This transformation is a shear mapping (transvection) that distorts each point within an element by a certain angle in the horizontal direction. The abscissa coordinate of each point is modified by a value proportionate to the specified angle and the distance to the origin; thus, the farther from the origin a point is, the greater will be the value added it.

skewX(a) is equivalent to skew(a).

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/skewX

skewY() Skews an element in the vertical direction.

The skewY() CSS function defines a transformation that skews an element in the vertical direction on the 2D plane.

This transformation is a shear mapping (transvection) that distorts each point within an element by a certain angle in the vertical direction. The ordinate coordinate of each point is modified by a value proportionate to the specified angle and the distance to the origin; thus, the farther from the origin a point is, the greater will be the value added it.

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/skewY


Close

-------------------------------------------------------------------------------- /dist/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CSS Transform Playground", 3 | "short_name": "css-transform", 4 | "lang": "en-US", 5 | "start_url": "/index.html?launcher=true", 6 | "display": "fullscreen", 7 | "orientation": "any", 8 | "theme_color": "#1a1718" 9 | } 10 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const { series, parallel, src, dest } = require('gulp'); 2 | const less = require('gulp-less'); 3 | const autoprefixer = require('autoprefixer'); 4 | const cssnano = require('cssnano'); 5 | const postcss = require('gulp-postcss'); 6 | const htmlmin = require('gulp-htmlmin'); 7 | const replace = require('gulp-replace'); 8 | const babel = require('gulp-babel'); 9 | const uglify = require('gulp-uglify'); 10 | const del = require('del'); 11 | const fs = require('fs'); 12 | 13 | function styles() { 14 | let plugins = [ 15 | autoprefixer(), 16 | cssnano() 17 | ]; 18 | return src('src/css/app.less') 19 | .pipe(less()) 20 | .pipe(postcss(plugins)) 21 | .pipe(dest('dist/css')); 22 | } 23 | function html() { 24 | return src('src/index.html') 25 | .pipe(replace(/..\/node_modules\/vue\/dist\/vue.js/g, 'js/vue.min.js')) 26 | .pipe(replace(/..\/node_modules\/chain-timeout\/dist\/chain-timeout.min.js/g, 'js/chain-timeout.min.js')) 27 | .pipe(htmlmin({ 28 | collapseWhitespace: true, 29 | removeComments: true 30 | })) 31 | .pipe(dest('dist/')); 32 | } 33 | function scripts() { 34 | return src('src/js/app.js') 35 | .pipe(babel({ 36 | presets: ['@babel/preset-env'] 37 | })) 38 | .pipe(uglify()) 39 | .pipe(dest('dist/js')); 40 | } 41 | function copy_files() { 42 | return src([ 43 | 'src/_redirects', 44 | 'src/manifest.json', 45 | ]) 46 | .pipe(dest('dist/')); 47 | } 48 | function modules() { 49 | return src([ 50 | 'node_modules/vue/dist/vue.min.js', 51 | 'node_modules/chain-timeout/dist/chain-timeout.min.js' 52 | ]) 53 | .pipe(dest('dist/js')); 54 | } 55 | 56 | // ... 57 | 58 | function clean_dist_before() { return del([ 'dist/**/*' ]) } 59 | function clean_dist_after() { 60 | 61 | return del([ 62 | 'dist/css/', 63 | 'dist/js/', 64 | ]); 65 | } 66 | 67 | function embed_external() { 68 | return src('dist/index.html') 69 | .pipe(replace( 70 | //g, 71 | (s, filename) => { 72 | let _css = fs.readFileSync(`dist/${filename}`, 'utf8'); 73 | return ``; 74 | } 75 | )) 76 | .pipe(replace( 77 | /`; 81 | } 82 | )) 83 | .pipe(dest('dist/')); 84 | } 85 | 86 | exports.prebuild = series(clean_dist_before); 87 | exports.create = parallel(styles, html, scripts, copy_files, modules); 88 | exports.embed = series(embed_external); 89 | exports.postbuild = series(clean_dist_after); 90 | 91 | exports.build = series(clean_dist_before, parallel(styles, html, scripts, copy_files, modules), embed_external, clean_dist_after); 92 | -------------------------------------------------------------------------------- /media/css-transform.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alterebro/css-transform/3c11eead0dfdb0936fc74516153aef80bc14cdad/media/css-transform.gif -------------------------------------------------------------------------------- /media/css-transform.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alterebro/css-transform/3c11eead0dfdb0936fc74516153aef80bc14cdad/media/css-transform.jpg -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css-transform", 3 | "version": "1.0.0", 4 | "description": "CSS Transform Functions Playground", 5 | "main": "src/app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "browserslist": [ 10 | "> 0.5%", 11 | "last 2 version", 12 | "Firefox ESR", 13 | "not dead" 14 | ], 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/alterebro/css-transform.git" 18 | }, 19 | "keywords": [ 20 | "CSS", 21 | "transform", 22 | "2D", 23 | "3D" 24 | ], 25 | "author": "Jorge Moreno @alterebro (moro.es)", 26 | "license": "MIT", 27 | "bugs": { 28 | "url": "https://github.com/alterebro/css-transform/issues" 29 | }, 30 | "homepage": "https://github.com/alterebro/css-transform#readme", 31 | "devDependencies": { 32 | "@babel/core": "^7.10.5", 33 | "@babel/preset-env": "^7.10.4", 34 | "autoprefixer": "^10.4.16", 35 | "chain-timeout": "^1.0.5", 36 | "cssnano": "^5.1.14", 37 | "del": "^4.1.1", 38 | "gulp": "^5.0.0", 39 | "gulp-babel": "^8.0.0", 40 | "gulp-htmlmin": "^5.0.1", 41 | "gulp-less": "^4.0.1", 42 | "gulp-postcss": "^9.0.1", 43 | "gulp-replace": "^1.0.0", 44 | "gulp-uglify": "^3.0.2", 45 | "vue": "^2.6.11" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/_redirects: -------------------------------------------------------------------------------- 1 | # Redirect default Netlify subdomain to primary domain 2 | https://css-transform.netlify.com/* https://css-transform.moro.es/:splat 301! 3 | -------------------------------------------------------------------------------- /src/css/app.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Inconsolata:400,700');html,body,h1,h2,h3,h4,p,ul,ol,li,dl,dd,dt,form,fieldset,hr,pre{margin:0;padding:0}li{list-style-type:none}article,aside,footer,header,main,menu,nav,section{display:block}button,input,optgroup,select,textarea{font:inherit;color:inherit;margin:0;padding:0;text-transform:none}::-moz-selection{background-color:#29d4b5;color:#fff;text-shadow:none}::selection{background-color:#29d4b5;color:#fff;text-shadow:none}html{line-height:1;text-size-adjust:100%;box-sizing:border-box;font-size:62.5%;tab-size:4;word-break:break-word;cursor:default}body{font-family:"Inconsolata","Andale Mono","Monaco","Lucida Console","Menlo","Consolas","Roboto Mono","Liberation Mono",monospace;font-size:1.6em;line-height:1.6;background:#1a1718;color:#e0e1e4}html,body{height:100%;width:100%;overflow:hidden}*,*:before,*:after{box-sizing:inherit;background-repeat:no-repeat}svg:not(:root){overflow:hidden}template,[hidden]{display:none}hr{display:none}a{color:#25a8bf;text-decoration:none;background-color:transparent;transition:color .25s ease-in-out}a:hover{color:#e7a817}a:active,a:hover{outline:0}pre,code,kbd,samp{font-family:"Inconsolata","Andale Mono","Monaco","Lucida Console","Menlo","Consolas","Roboto Mono","Liberation Mono",monospace}pre{white-space:pre;white-space:pre-wrap;word-wrap:break-word;overflow:auto}pre>code{white-space:pre;display:block}input[type="range"]{-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none;border-radius:2px;box-shadow:none;height:12px;background:#352f31}input[type="range"]::-webkit-slider-runnable-track{height:12px;width:100%;background:#352f31;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none;border-radius:2px;box-shadow:none}input[type="range"]::-moz-range-track{height:12px;width:100%;background:#352f31;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none;border-radius:2px;box-shadow:none}input[type="range"]::-ms-track{height:12px;width:100%;background:#352f31;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none;border-radius:2px;box-shadow:none}input[type="range"]::-ms-fill-lower,input[type="range"]::-ms-fill-upper{background:#352f31;border:none;border-radius:2px;box-shadow:none}input[type="range"]::-webkit-slider-thumb{height:12px;width:12px;background:#25a8bf;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none;border-radius:2px;box-shadow:none;transition:background .35s ease-in-out}input[type="range"]::-moz-range-thumb{height:12px;width:12px;background:#25a8bf;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none;border-radius:2px;box-shadow:none;transition:background .35s ease-in-out}input[type="range"]::-ms-thumb{height:12px;width:12px;background:#25a8bf;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none;border-radius:2px;box-shadow:none;transition:background .35s ease-in-out}input[type="range"]:focus{outline:none}input[type="range"]:hover::-webkit-slider-runnable-track{background:#352f31}input[type="range"]:hover::-moz-range-track{background:#352f31}input[type="range"]:hover::-ms-fill-lower{background:#352f31}input[type="range"]:hover::-ms-fill-upper{background:#352f31}input[type="range"]:hover::-webkit-slider-thumb{background:#e7a817}input[type="range"]:hover::-moz-range-thumb{background:#e7a817}input[type="range"]:hover::-ms-thumb{background:#e7a817}input[type="range"]::-moz-focus-outer{border:0}button{display:inline-block;padding:0 10px;background-color:#25a8bf;border:none;border-radius:2px;color:rgba(255,255,255,0.75);cursor:pointer}button[class^="btn-"]{background-repeat:no-repeat;background-size:10px 10px;background-position:right 10px center;padding:0 25px 0 10px;transition:background .25s ease-in-out,color .25s ease-in-out}button.btn-random{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='%23fff' d='M505 359c9 9 9 25 0 34l-80 80c-15 15-41 4-41-17v-40h-59a12 12 0 0 1-9-4l-70-75 53-58 53 57h32v-40c0-21 26-32 41-17l80 80zM12 176h84l53 57 53-58-70-75a12 12 0 0 0-9-4H12c-7 0-12 5-12 12v56c0 7 5 12 12 12zm372 0v40c0 21 26 32 41 17l80-80c9-9 9-25 0-34l-80-80c-15-15-41-4-41 17v40h-59a12 12 0 0 0-9 4L96 336H12c-7 0-12 5-12 12v56c0 7 5 12 12 12h111c3 0 6-1 9-4l220-236h32z'/%3E%3C/svg%3E")}button.btn-reset{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='%23fff' d='M400 54a248 248 0 1 1-288 0c11-8 28-5 35 8l16 28c5 11 3 24-7 31a168 168 0 1 0 200 0c-10-7-13-21-7-31l16-28c7-13 23-16 35-8zM296 264V24c0-13-11-24-24-24h-32c-13 0-24 11-24 24v240c0 13 11 24 24 24h32c13 0 24-11 24-24z'/%3E%3C/svg%3E")}button.btn-on,button.btn-off{background-size:12px auto;background-position:right 8px center}button.btn-on{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath fill='%23fff' d='M576 256c0 106-86 192-192 192H192a192 192 0 1 1 0-384h192c106 0 192 86 192 192zM384 128a128 128 0 1 0 0 256 128 128 0 0 0 0-256'/%3E%3C/svg%3E")}button.btn-off{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath fill='%23fff' d='M384 64H192a192 192 0 1 0 0 384h192a192 192 0 1 0 0-384zM64 256a128 128 0 1 1 256 0 128 128 0 0 1-256 0zm320 128h-49c65-73 65-183 0-256h49a128 128 0 1 1 0 256z'/%3E%3C/svg%3E")}button:hover{background-color:#d06815;color:rgba(255,255,255,0.99)}button:focus{outline:none}label.checkboxed{position:relative;padding-left:30px;cursor:pointer}label.checkboxed input[type="checkbox"]{display:none}label.checkboxed input[type="checkbox"]+strong:before{content:'';display:block;width:12px;height:12px;background:transparent;border:solid #9c9fa9 1px;position:absolute;left:10px;top:50%;margin-top:-6px;border-radius:2px;transition:background .25s ease-in-out,box-shadow .25s ease-in-out}label.checkboxed input[type="checkbox"]:checked+strong:before{background:#29d4b5;box-shadow:inset 0 0 0 2px #000}#app{position:fixed;top:0;left:0;width:100%;height:100%;overflow:hidden;font-size:1.3rem;background-image:radial-gradient(circle farthest-side, rgba(33,126,170,0.5), transparent),radial-gradient(farthest-corner at 10% 90%, rgba(41,212,181,0.2), transparent 80%);background-size:90vw 90vw, 100% 100%;background-position:center center}#app:after{content:'';display:block;position:absolute;top:0;left:0;width:100%;height:4px;background-image:linear-gradient(90deg, #217eaa, #25a8bf, #29d4b5, #e7a817, #d06815, #b94113);box-shadow:0 1px 0 0 rgba(0,0,0,0.35)}section#do{z-index:3;position:fixed;top:0;right:0}section#do a{transition:all .25s ease-in-out;position:absolute;top:2rem;right:2rem;height:4rem;width:4rem;border-radius:3px;box-shadow:inset 0 0 0 1px rgba(255,255,255,0.2)}section#do a:hover{box-shadow:inset 0 0 0 1px rgba(255,255,255,0.4)}section#do a em{display:block;text-indent:-1000rem;position:absolute;transform:translateY(-50%);top:50%;left:12px;width:16px}section#do a#open{right:2rem;opacity:1}section#do a#open em{border-top:solid #fff 2px;border-bottom:solid #fff 2px;height:14px}section#do a#open em:after{content:'';display:block;width:100%;height:2px;background:#fff;position:absolute;top:50%;margin-top:-1px}section#do a#close{right:-6rem;opacity:0}section#do a#close em{height:16px}section#do a#close em:before,section#do a#close em:after{content:'';display:block;width:21.627417px;height:2px;background:#fff;position:absolute}section#do a#close em:before{top:0;left:0;transform:rotate(45deg);transform-origin:1px 1px}section#do a#close em:after{bottom:0;left:0;transform:rotate(-45deg);transform-origin:1px 1px}header{z-index:2;position:fixed;top:0;right:-42rem;height:80px;width:100%;max-width:42rem;background:rgba(0,0,0,0.65);padding:2rem;box-shadow:inset 0 4px 0 #25a8bf,inset 0 5px 0 #000,0 2px 0 0 rgba(0,0,0,0.5);border-bottom:solid rgba(37,168,191,0.5) 1px;overflow:hidden;transition:right .25s ease-in-out}header h1,header p{width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;padding:0 50px 0 0}header h1{font-size:2.2rem;font-weight:700;color:#fff;margin:0 0 2px;line-height:1;height:22px}header p{line-height:1.4;height:18px}aside{z-index:1;position:fixed;top:80px;right:-42rem;height:calc(100% - 80px);width:100%;max-width:42rem;background:rgba(0,0,0,0.65);overflow:auto;transition:right .25s ease-in-out}aside form{padding:2rem}aside form fieldset{border:none}aside form fieldset>legend{font-weight:700}aside form fieldset>dl dt:first-child{margin-top:1rem}aside form fieldset>dl dt{margin:1.5rem 0 .5rem 0;display:flex;justify-content:space-between;align-items:center;line-height:30px;background:#000;border-radius:3px}aside form fieldset>dl dt>label{flex:1 1 auto}aside form fieldset>dl dt>a{flex:0 0 auto;display:block;padding:0 30px 0 16px;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='%23fff' d='M504 256a248 248 0 1 1-496 0 248 248 0 0 1 496 0zM263 90c-55 0-90 23-117 64-3 5-2 12 3 16l35 26c5 4 12 3 16-2 18-22 30-36 57-36 21 0 46 14 46 33 0 15-12 23-32 34-24 14-55 30-55 71v4c0 7 5 12 12 12h56c7 0 12-5 12-12v-1c0-29 83-30 83-107 0-58-60-102-116-102zm-7 248a46 46 0 1 0 0 92 46 46 0 0 0 0-92z'/%3E%3C/svg%3E");background-position:right 12px center;background-size:10px;background-repeat:no-repeat}aside form fieldset>dl dd{padding:.2rem 0}aside form fieldset>dl dd:not(.buttons){display:flex;align-items:center;justify-content:space-between}aside form fieldset>dl dd:not(.buttons) label{display:inline-block;padding-left:5px;min-width:14.5rem;flex:0 0 14.5rem}aside form fieldset>dl dd:not(.buttons) input{display:block;width:100%;flex:1 1 auto}aside form fieldset>dl dd:not(.buttons) code{display:inline-block;text-align:right;padding:0 5px 0 0;font-size:.9em;flex:0 0 5rem;color:#9c9fa9}aside form fieldset>dl dd.buttons{text-align:right;padding:.5rem 5rem 0 0}aside form fieldset>p{margin-top:2rem;overflow:auto}aside form fieldset>p button{float:left;margin:0 .5rem .5rem 0}aside form fieldset:last-child{margin:3rem 0 0 0}aside form fieldset:last-child p{margin:1rem 0 0 0}main{width:100%;height:100%;display:flex;justify-content:center;align-items:center;padding:0;transition:width .1s linear}main #box{display:inline-block;height:80vh;width:80vh;background:rgba(0,0,0,0.5);box-shadow:0 0 0 1px rgba(37,168,191,0.5);position:relative}@media all and (orientation: landscape){main #box{height:80vh;width:80vh}}@media all and (orientation: portrait){main #box{height:80vw;width:80vw}}main #alpha{position:absolute;border:solid white 10px;width:calc(100% - 20px);height:calc(100% - 20px);margin:10px;transition:all .5s ease-in-out;transform-style:preserve-3d;-webkit-transform-style:preserve-3d}main #alpha:before,main #alpha:after{content:'';display:block;position:absolute}main #alpha:before{top:50%;left:-15%;height:0;width:130%;border-top:dotted rgba(255,255,255,0.5) 1px}main #alpha:after{top:-15%;left:50%;height:130%;width:0;border-left:dotted rgba(255,255,255,0.5) 1px}main #alpha .alpha-panel{display:flex;justify-content:center;align-items:center;position:absolute;top:-10px;left:-10px;width:calc(100% + 20px);height:calc(100% + 20px);box-shadow:inset 0 0 0 10px rgba(37,168,191,0.5);background-color:rgba(0,0,0,0.1);opacity:0;transition:all .35s ease-in-out}main #alpha .alpha-panel.active{opacity:1}main #alpha .alpha-panel strong{opacity:0;font-size:24px;font-weight:normal;color:#fff;text-transform:uppercase;letter-spacing:2px;transition:opacity .35s ease-in-out}main #alpha .alpha-panel:hover{box-shadow:inset 0 0 0 10px #d06815;background-color:rgba(0,0,0,0.5)}main #alpha .alpha-panel:hover strong{opacity:1}main #alpha #alpha-front{transform:translateZ(100px)}main #alpha #alpha-back{transform:translateZ(-100px)}#app.with-sidebar section#do a#open{right:44rem;opacity:0}#app.with-sidebar section#do a#close{right:2rem;opacity:1}#app.with-sidebar header{right:0}#app.with-sidebar aside{right:0}@media all and (min-width: 960px){#app.with-sidebar main{width:calc(100% - 42rem)}}article{z-index:10;display:flex;position:fixed;top:0;left:0;width:100%;height:100%;flex-direction:column;justify-content:center;align-items:center;opacity:0;background:rgba(0,0,0,0);transition:all .25s ease-in-out}article.visible{opacity:1;background:rgba(0,0,0,0.75)}article.gone{display:none}article>section{order:2;display:none;width:90%;max-width:72rem;padding:4rem;background:#000;border:solid rgba(37,168,191,0.5) 1px}article>section h2{font-size:2rem;line-height:1;margin:0;font-weight:400}article>section h3{font-size:1.6rem;color:#9c9fa9;margin:0 0 1rem}article>section p{margin:0 0 1rem}article>section ul{margin:0 0 1rem 2rem}article>section ul li{list-style:square;margin:0 0 .5rem}article>section ul li:last-child{margin:0}article>section details{padding:1rem 0 0}article>section details summary{cursor:pointer}article>section details summary h3{display:inline-block;margin:0}article>section details summary[open]{margin:0 0 1rem}article>section details summary:focus{outline:none}article>section pre{border:dotted #9c9fa9 1px;border-radius:3px;margin:1rem 0 2rem}article>section pre>code{font-size:.9em;color:#9c9fa9;padding:1rem 2rem}article>p{order:1;width:90%;max-width:72rem;text-align:right;position:relative}article>p a{display:block;position:absolute;top:3rem;right:3rem;font-size:1.2rem}footer{z-index:0;position:fixed;bottom:0;left:0;padding:1rem;font-size:.9em;background:rgba(0,0,0,0.65);border-top-right-radius:3px}footer p{line-height:1.5;padding:0 5px 0 0}footer dl{border-bottom:solid rgba(37,168,191,0.5) 1px;margin:0 0 .5rem;padding:0}footer dl dt{margin:0;padding:0 0 .5rem 16px;cursor:pointer;position:relative;font-weight:bold;color:#25a8bf;transition:color .25s ease-in-out}footer dl dt:hover{color:#e7a817}footer dl dt:before{content:'';display:block;position:absolute;top:6px;left:4px;width:6px;height:6px;border-top:solid 6px #e0e1e4;border-left:solid 3px transparent;border-right:solid 3px transparent;border-bottom:none;transition:transform .35s ease-in-out;transform-origin:center center;transform:rotate(-90deg)}footer dl dt.visible:before{transform:rotate(0deg)}footer dl dd{max-height:0;overflow:hidden;transition:max-height .35s ease-in-out}footer dl dd pre{border:dotted #9c9fa9 1px;margin:0 0 1rem;padding:0}footer dl dd pre>code{margin:0;padding:1rem;color:#fff;cursor:text}footer dl dd.visible{max-height:320px} -------------------------------------------------------------------------------- /src/css/app.less: -------------------------------------------------------------------------------- 1 | // Media Queries 2 | @mobile-breakpoint : 660px; 3 | @desktop-breakpoint : 960px; 4 | 5 | @mobile : ~"all and (max-width: @{mobile-breakpoint})"; // default 6 | @non-mobile : ~"all and (min-width: @{mobile-breakpoint})"; // matching both @tablet and @desktop 7 | @tablet : ~"all and (min-width: @{mobile-breakpoint}) and (max-width: @{desktop-breakpoint})"; 8 | @desktop : ~"all and (min-width: @{desktop-breakpoint})"; 9 | @portrait : ~"all and (orientation: portrait)"; 10 | @landscape : ~"all and (orientation: landscape)"; 11 | 12 | // Fonts 13 | @import url('https://fonts.googleapis.com/css?family=Inconsolata:400,700'); 14 | @sans : -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Droid Sans", "Helvetica Neue", Arial, sans-serif; 15 | @mono : "Andale Mono", "Monaco", "Lucida Console", "Menlo", "Consolas", "Roboto Mono", "Liberation Mono", monospace; 16 | @font-sans : "Inconsolata", @mono; 17 | @font-mono : @font-sans; 18 | 19 | // Colurs 20 | @color-bg : #1a1718; 21 | @color-bg-light : lighten(@color-bg, 10%); 22 | @color-bg-dark : #000; 23 | @color-fg : #e0e1e4; 24 | @color-fg-light : #fff; 25 | @color-fg-dark : darken(@color-fg, 25%); 26 | @color-alpha : #25a8bf; // #05889f; 27 | @color-alpha-light : lighten(spin(@color-alpha, -20), 5%); 28 | @color-alpha-dark : darken(spin(@color-alpha, 10), 5%); 29 | @color-beta : #d06815; // #c05805; 30 | @color-beta-light : lighten(spin(@color-beta, 15), 5%); 31 | @color-beta-dark : darken(spin(@color-beta, -10), 5%); 32 | 33 | 34 | // -------------------------------------------- 35 | // Pseudo-Reset 36 | html, body, h1, h2, h3, h4, p, ul, ol, li, dl, dd, dt, form, fieldset, hr , pre { 37 | margin: 0; 38 | padding: 0; 39 | } 40 | li { list-style-type: none; } 41 | article, aside, footer, header, main, menu, nav, section { 42 | display: block; 43 | } 44 | button, input, optgroup, select, textarea { 45 | font: inherit; 46 | color: inherit; 47 | margin: 0; 48 | padding: 0; 49 | text-transform: none; 50 | } 51 | 52 | ::-moz-selection { 53 | background-color: @color-alpha-light; 54 | color: @color-fg-light; 55 | text-shadow: none; 56 | } 57 | ::selection { 58 | background-color: @color-alpha-light; 59 | color: @color-fg-light; 60 | text-shadow: none; 61 | } 62 | 63 | // ----------------------- 64 | 65 | html { 66 | line-height: 1; 67 | text-size-adjust: 100%; 68 | box-sizing: border-box; 69 | font-size: 62.5%; 70 | tab-size: 4; 71 | word-break: break-word; 72 | cursor: default; 73 | } 74 | body { 75 | font-family: @font-sans; 76 | font-size: 1.6em; 77 | line-height: 1.6; 78 | background: @color-bg; 79 | color: @color-fg; 80 | } 81 | html, body { 82 | height: 100%; 83 | width: 100%; 84 | overflow: hidden; 85 | } 86 | *, *:before, *:after { 87 | box-sizing: inherit; 88 | background-repeat: no-repeat; 89 | } 90 | svg:not(:root) { overflow: hidden; } 91 | template, [hidden] { display: none; } 92 | hr { display: none; } 93 | 94 | a { 95 | color: @color-alpha; 96 | text-decoration: none; 97 | background-color: transparent; 98 | 99 | transition: color .25s ease-in-out; 100 | } 101 | a:hover { color: @color-beta-light; } 102 | a:active, a:hover { outline: 0; } 103 | 104 | pre, code, kbd, samp { font-family: @font-mono; } 105 | pre { 106 | white-space: pre; 107 | white-space: pre-wrap; 108 | word-wrap: break-word; 109 | overflow: auto; 110 | 111 | > code { 112 | white-space: pre; 113 | display: block; 114 | } 115 | } 116 | 117 | // ----------------------------------------- 118 | // Input range styling : input[type="range"] 119 | @range-height : 12px; 120 | @range-track-bg : @color-bg-light; 121 | @range-track-active-bg : @color-bg-light; 122 | @range-handler-bg : @color-alpha; 123 | @range-handler-active-bg : @color-beta-light; 124 | 125 | .appears-like(@value) { 126 | -webkit-appearance: @value; 127 | -moz-appearance: @value; 128 | appearance: @value; 129 | } 130 | .appears-clean() { 131 | border: none; 132 | border-radius: 2px; 133 | box-shadow: none; 134 | } 135 | .range-input-reset() { 136 | .appears-like(none); 137 | .appears-clean() 138 | } 139 | .range-track() { 140 | height: @range-height; 141 | width: 100%; 142 | background: @range-track-bg; 143 | cursor: pointer; 144 | .range-input-reset(); 145 | // transition: background .35s ease-in-out; 146 | } 147 | .range-track-active() { background: @range-track-active-bg; } 148 | .range-handler() { 149 | height: @range-height; 150 | width: @range-height; 151 | background: @range-handler-bg; 152 | cursor: pointer; 153 | .range-input-reset(); 154 | transition: background .35s ease-in-out; 155 | } 156 | .range-handler-active() { background: @range-handler-active-bg; } 157 | 158 | input[type="range"] { 159 | 160 | .range-input-reset(); 161 | height: @range-height; 162 | background: @range-track-bg; 163 | 164 | // Slider / Track 165 | &::-webkit-slider-runnable-track { .range-track() } 166 | &::-moz-range-track { .range-track() } 167 | &::-ms-track { .range-track() } 168 | &::-ms-fill-lower, 169 | &::-ms-fill-upper { 170 | background: @range-track-bg; 171 | .appears-clean(); 172 | } 173 | 174 | // Handler 175 | &::-webkit-slider-thumb { .range-handler() } 176 | &::-moz-range-thumb { .range-handler() } 177 | &::-ms-thumb { .range-handler() } 178 | 179 | &:focus { outline: none; } 180 | &:hover { 181 | 182 | &::-webkit-slider-runnable-track { .range-track-active() } 183 | &::-moz-range-track { .range-track-active() } 184 | &::-ms-fill-lower { .range-track-active() } 185 | &::-ms-fill-upper { .range-track-active() } 186 | 187 | &::-webkit-slider-thumb { .range-handler-active() } 188 | &::-moz-range-thumb { .range-handler-active() } 189 | &::-ms-thumb { .range-handler-active() } 190 | } 191 | 192 | // Normalizing... 193 | &::-moz-focus-outer { border: 0; } 194 | } 195 | 196 | // ----------------------------------------- 197 | // Input Button : button, input[type="button"], input[type="submit"] ... 198 | button { 199 | display: inline-block; 200 | padding: 0 10px; 201 | background-color: @color-alpha; 202 | border: none; 203 | border-radius: 2px; 204 | color: fade(@color-fg-light, 75%); 205 | cursor: pointer; 206 | // text-shadow: 0 -1px 0 rgba(0, 0, 0, .1); 207 | 208 | &[class^="btn-"] { 209 | background-repeat: no-repeat; 210 | background-size: 10px 10px; 211 | background-position: right 10px center; 212 | padding: 0 25px 0 10px; 213 | transition: 214 | background .25s ease-in-out, 215 | color .25s ease-in-out; 216 | } 217 | &.btn-random { background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='%23fff' d='M505 359c9 9 9 25 0 34l-80 80c-15 15-41 4-41-17v-40h-59a12 12 0 0 1-9-4l-70-75 53-58 53 57h32v-40c0-21 26-32 41-17l80 80zM12 176h84l53 57 53-58-70-75a12 12 0 0 0-9-4H12c-7 0-12 5-12 12v56c0 7 5 12 12 12zm372 0v40c0 21 26 32 41 17l80-80c9-9 9-25 0-34l-80-80c-15-15-41-4-41 17v40h-59a12 12 0 0 0-9 4L96 336H12c-7 0-12 5-12 12v56c0 7 5 12 12 12h111c3 0 6-1 9-4l220-236h32z'/%3E%3C/svg%3E"); } 218 | &.btn-reset { background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='%23fff' d='M400 54a248 248 0 1 1-288 0c11-8 28-5 35 8l16 28c5 11 3 24-7 31a168 168 0 1 0 200 0c-10-7-13-21-7-31l16-28c7-13 23-16 35-8zM296 264V24c0-13-11-24-24-24h-32c-13 0-24 11-24 24v240c0 13 11 24 24 24h32c13 0 24-11 24-24z'/%3E%3C/svg%3E"); } 219 | 220 | &.btn-on, &.btn-off { 221 | background-size: 12px auto; 222 | background-position: right 8px center; 223 | } 224 | &.btn-on { background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath fill='%23fff' d='M576 256c0 106-86 192-192 192H192a192 192 0 1 1 0-384h192c106 0 192 86 192 192zM384 128a128 128 0 1 0 0 256 128 128 0 0 0 0-256'/%3E%3C/svg%3E"); } 225 | &.btn-off { background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath fill='%23fff' d='M384 64H192a192 192 0 1 0 0 384h192a192 192 0 1 0 0-384zM64 256a128 128 0 1 1 256 0 128 128 0 0 1-256 0zm320 128h-49c65-73 65-183 0-256h49a128 128 0 1 1 0 256z'/%3E%3C/svg%3E"); } 226 | 227 | &:hover { 228 | background-color: @color-beta; 229 | color: fade(@color-fg-light, 99%); 230 | } 231 | &:focus { outline: none; } 232 | } 233 | 234 | // ----------------------------------------- 235 | // Input Checkbox : input[type="checkbox"] / (Within label with sibling) 236 | label.checkboxed { 237 | position: relative; 238 | padding-left: 30px; 239 | cursor: pointer; 240 | 241 | input[type="checkbox"] { display: none; } 242 | input[type="checkbox"] + strong:before { 243 | content: ''; 244 | display: block; 245 | width: 12px; 246 | height: 12px; 247 | background: transparent; 248 | border: solid @color-fg-dark 1px; 249 | position: absolute; 250 | left: 10px; 251 | top: 50%; 252 | margin-top: -6px; 253 | border-radius: 2px; 254 | 255 | transition: background .25s ease-in-out, box-shadow .25s ease-in-out; 256 | } 257 | input[type="checkbox"]:checked + strong:before { 258 | background: @color-alpha-light; 259 | box-shadow: inset 0 0 0 2px #000; 260 | } 261 | } 262 | 263 | // ----------------------- 264 | 265 | 266 | 267 | 268 | #app { 269 | position: fixed; 270 | top: 0; 271 | left: 0; 272 | width: 100%; 273 | height: 100%; 274 | overflow: hidden; 275 | font-size: 1.3rem; 276 | 277 | background-image: 278 | radial-gradient(circle farthest-side, fade(@color-alpha-dark, 50%), transparent), 279 | radial-gradient(farthest-corner at 10% 90%, fade(@color-alpha-light, 20%), transparent 80%); 280 | background-size: 90vw 90vw, 100% 100%; 281 | background-position: center center; 282 | 283 | &:after { 284 | content: ''; 285 | display: block; 286 | position: absolute; 287 | top: 0; 288 | left: 0; 289 | width: 100%; 290 | height: 4px; 291 | background-image: linear-gradient( 90deg, 292 | @color-alpha-dark, 293 | @color-alpha, 294 | @color-alpha-light, 295 | @color-beta-light, 296 | @color-beta, 297 | @color-beta-dark 298 | ); 299 | box-shadow: 0 1px 0 0 rgba(0, 0, 0, .35); 300 | } 301 | } 302 | 303 | section#do { 304 | z-index: 3; 305 | position: fixed; 306 | top: 0; 307 | right: 0; 308 | 309 | a { 310 | transition: all .25s ease-in-out; 311 | 312 | position: absolute; 313 | top: 2rem; 314 | right: 2rem; 315 | height: 4rem; 316 | width: 4rem; 317 | border-radius: 3px; 318 | box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .2); 319 | 320 | &:hover { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .4) } 321 | 322 | em { 323 | display: block; 324 | text-indent: -1000rem; 325 | position: absolute; 326 | transform: translateY(-50%); 327 | top: 50%; 328 | left: 12px; 329 | width: 16px; 330 | } 331 | } 332 | 333 | a#open { // ≡ 334 | 335 | right: 2rem; 336 | opacity: 1; 337 | 338 | em { 339 | 340 | border-top: solid #fff 2px; 341 | border-bottom: solid #fff 2px; 342 | height: 14px; // 16px; 343 | 344 | &:after { 345 | content: ''; 346 | display: block; 347 | width: 100%; 348 | height: 2px; 349 | background: #fff; 350 | position: absolute; 351 | top: 50%; 352 | margin-top: -1px; 353 | } 354 | } 355 | } 356 | 357 | a#close { // × 358 | 359 | right: -6rem; 360 | opacity: 0; 361 | 362 | em { 363 | 364 | height: 16px; 365 | 366 | &:before, &:after { 367 | content: ''; 368 | display: block; 369 | width: (sqrt(2) * 16px) - 1px; 370 | height: 2px; 371 | background: #fff; 372 | position: absolute; 373 | } 374 | &:before { 375 | top: 0; 376 | left: 0; 377 | transform: rotate(45deg); 378 | transform-origin: 1px 1px; 379 | } 380 | 381 | &:after { 382 | bottom: 0; 383 | left: 0; 384 | transform: rotate(-45deg); 385 | transform-origin: 1px 1px; 386 | } 387 | } 388 | } 389 | } 390 | 391 | // ----------------------- 392 | 393 | @aside-bg : rgba(0, 0, 0, .65); 394 | @aside-width : 42rem; 395 | 396 | header { 397 | 398 | z-index: 2; 399 | position: fixed; 400 | top: 0; 401 | right: -(@aside-width); 402 | 403 | height: 80px; 404 | width: 100%; 405 | max-width: @aside-width; 406 | background: @aside-bg; 407 | padding: 2rem; 408 | box-shadow: 409 | inset 0 4px 0 @color-alpha, 410 | inset 0 5px 0 #000, 411 | 0 2px 0 0 rgba(0, 0, 0, .5); 412 | 413 | border-bottom: solid fade(@color-alpha, 50%) 1px; 414 | overflow: hidden; 415 | 416 | transition: right .25s ease-in-out; 417 | 418 | h1, p { 419 | width: 100%; 420 | overflow: hidden; 421 | white-space: nowrap; 422 | text-overflow: ellipsis; 423 | padding: 0 50px 0 0; 424 | } 425 | 426 | h1 { 427 | font-size: 2.2rem; 428 | font-weight: 700; 429 | color: @color-fg-light; 430 | margin: 0 0 2px; 431 | line-height: 1; 432 | height: 22px; 433 | } 434 | p { 435 | line-height: 1.4; 436 | height: 18px; 437 | } 438 | } 439 | 440 | aside { 441 | z-index: 1; 442 | position: fixed; 443 | top: 80px; 444 | right: -(@aside-width); 445 | 446 | height: ~"calc(100% - 80px)"; 447 | width: 100%; 448 | max-width: @aside-width; 449 | background: @aside-bg; 450 | overflow: auto; 451 | 452 | transition: right .25s ease-in-out; 453 | 454 | form { 455 | padding: 2rem; 456 | 457 | fieldset { 458 | border: none; 459 | 460 | > legend { font-weight: 700 } 461 | > dl { 462 | dt:first-child { margin-top: 1rem; } 463 | dt { 464 | margin: 1.5rem 0 .5rem 0; 465 | display: flex; 466 | justify-content: space-between; 467 | align-items: center; 468 | line-height: 30px; 469 | background: @color-bg-dark; 470 | border-radius: 3px; 471 | 472 | > label { flex: 1 1 auto; } 473 | > a { 474 | flex: 0 0 auto; 475 | display: block; 476 | padding: 0 30px 0 16px; 477 | 478 | background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath fill='%23fff' d='M504 256a248 248 0 1 1-496 0 248 248 0 0 1 496 0zM263 90c-55 0-90 23-117 64-3 5-2 12 3 16l35 26c5 4 12 3 16-2 18-22 30-36 57-36 21 0 46 14 46 33 0 15-12 23-32 34-24 14-55 30-55 71v4c0 7 5 12 12 12h56c7 0 12-5 12-12v-1c0-29 83-30 83-107 0-58-60-102-116-102zm-7 248a46 46 0 1 0 0 92 46 46 0 0 0 0-92z'/%3E%3C/svg%3E"); 479 | background-position: right 12px center; 480 | background-size: 10px; 481 | background-repeat: no-repeat; 482 | } 483 | } 484 | dd { padding: .2rem 0; } 485 | dd:not(.buttons) { 486 | display: flex; 487 | align-items: center; 488 | justify-content: space-between; 489 | 490 | label { 491 | display: inline-block; 492 | padding-left: 5px; 493 | min-width: 14.5rem; 494 | flex: 0 0 14.5rem; 495 | } 496 | input { 497 | display: block; 498 | width: 100%; 499 | flex: 1 1 auto; 500 | } 501 | code { 502 | display: inline-block; 503 | text-align: right; 504 | padding: 0 5px 0 0; 505 | font-size: .9em; 506 | flex: 0 0 5rem; 507 | color: @color-fg-dark; 508 | } 509 | } 510 | dd.buttons { 511 | text-align: right; 512 | padding: .5rem 5rem 0 0; 513 | } 514 | } 515 | 516 | > p { 517 | margin-top: 2rem; 518 | overflow: auto; 519 | 520 | button { 521 | float: left; 522 | margin: 0 .5rem .5rem 0; 523 | } 524 | } 525 | } 526 | 527 | fieldset:last-child { 528 | margin: 3rem 0 0 0; 529 | p { margin: 1rem 0 0 0; } 530 | } 531 | } 532 | } 533 | 534 | main { 535 | width: 100%; 536 | height: 100%; 537 | display: flex; 538 | justify-content: center; 539 | align-items: center; 540 | padding: 0; 541 | transition: width .1s linear; 542 | 543 | #box { 544 | display: inline-block; 545 | height: 80vh; 546 | width: 80vh; 547 | background: fade(@color-bg-dark, 50%); 548 | box-shadow: 0 0 0 1px fade(@color-alpha, 50%); 549 | position: relative; 550 | 551 | @media @landscape { 552 | height: 80vh; 553 | width: 80vh; 554 | } 555 | @media @portrait { 556 | height: 80vw; 557 | width: 80vw; 558 | } 559 | } 560 | 561 | #alpha { 562 | position: absolute; 563 | border: solid white 10px; 564 | width: ~"calc(100% - 20px)"; 565 | height: ~"calc(100% - 20px)"; 566 | margin: 10px; 567 | transition: all .5s ease-in-out; 568 | 569 | &:before, &:after { 570 | content: ''; 571 | display: block; 572 | position: absolute; 573 | } 574 | &:before { 575 | top: 50%; 576 | left: -15%; 577 | height: 0; 578 | width: 130%; 579 | border-top: dotted fade(@color-fg-light, 50%) 1px; 580 | } 581 | &:after { 582 | top: -15%; 583 | left: 50%; 584 | height: 130%; 585 | width: 0; 586 | border-left: dotted fade(@color-fg-light, 50%) 1px; 587 | } 588 | 589 | transform-style: preserve-3d; 590 | -webkit-transform-style: preserve-3d; 591 | 592 | .alpha-panel { 593 | display: flex; 594 | justify-content: center; 595 | align-items: center; 596 | position: absolute; 597 | 598 | top: -10px; 599 | left: -10px; 600 | width: ~"calc(100% + 20px)"; 601 | height: ~"calc(100% + 20px)"; 602 | box-shadow: inset 0 0 0 10px fade(@color-alpha, 50%); 603 | background-color: rgba(0, 0, 0, .1); 604 | opacity: 0; 605 | transition: all .35s ease-in-out; 606 | 607 | &.active { opacity: 1 } 608 | 609 | strong { 610 | opacity: 0; 611 | font-size: 24px; 612 | font-weight: normal; 613 | color: @color-fg-light; 614 | text-transform: uppercase; 615 | letter-spacing: 2px; 616 | 617 | transition: opacity .35s ease-in-out; 618 | } 619 | 620 | &:hover { 621 | box-shadow: inset 0 0 0 10px @color-beta; 622 | background-color: rgba(0, 0, 0, .5); 623 | strong { opacity: 1; } 624 | } 625 | } 626 | #alpha-front { transform: translateZ(100px) } 627 | #alpha-back { transform: translateZ(-100px) } 628 | } 629 | } 630 | 631 | 632 | #app.with-sidebar { 633 | 634 | section#do { 635 | 636 | a#open { // ≡ 637 | right: @aside-width + 2rem; 638 | opacity: 0; 639 | } 640 | 641 | a#close { // × 642 | right: 2rem; 643 | opacity: 1; 644 | } 645 | } 646 | 647 | header { right: 0 } 648 | aside { right: 0 } 649 | main { 650 | @media @desktop { 651 | width: ~"calc(100% - @{aside-width})"; 652 | } 653 | } 654 | } 655 | 656 | 657 | // ----------------- 658 | // Info Modal Window 659 | 660 | article { 661 | z-index: 10; 662 | display: flex; 663 | position: fixed; 664 | top: 0; 665 | left: 0; 666 | width: 100%; 667 | height: 100%; 668 | flex-direction: column; 669 | justify-content: center; 670 | align-items: center; 671 | 672 | opacity: 0; 673 | background: rgba(0, 0, 0, 0); 674 | transition: all .25s ease-in-out; 675 | 676 | &.visible { 677 | opacity: 1; 678 | background: rgba(0, 0, 0, .75); 679 | } 680 | &.gone { display: none; } 681 | 682 | > section { 683 | order: 2; 684 | display: none; 685 | width: 90%; 686 | max-width: 72rem; 687 | padding: 4rem; 688 | background: @color-bg-dark; 689 | border: solid fade(@color-alpha, 50%) 1px; 690 | 691 | h2 { 692 | font-size: 2rem; 693 | line-height: 1; 694 | margin: 0; 695 | font-weight: 400; 696 | } 697 | h3 { 698 | font-size: 1.6rem; 699 | color: @color-fg-dark; 700 | margin: 0 0 1rem; 701 | } 702 | 703 | p { margin: 0 0 1rem; } 704 | 705 | ul { 706 | margin: 0 0 1rem 2rem; 707 | 708 | li { 709 | list-style: square; 710 | margin: 0 0 .5rem; 711 | &:last-child { margin: 0 } 712 | } 713 | } 714 | 715 | details { 716 | padding: 1rem 0 0; 717 | summary { 718 | cursor: pointer; 719 | h3 { 720 | display: inline-block; 721 | margin: 0; 722 | } 723 | &[open] { margin: 0 0 1rem; } 724 | &:focus { outline: none; } 725 | } 726 | } 727 | 728 | pre { 729 | border: dotted @color-fg-dark 1px; 730 | border-radius: 3px; 731 | margin: 1rem 0 2rem; 732 | 733 | > code { 734 | font-size: .9em; 735 | color: @color-fg-dark; 736 | padding: 1rem 2rem; 737 | } 738 | } 739 | } 740 | 741 | > p { 742 | order: 1; 743 | width: 90%; 744 | max-width: 72rem; 745 | text-align: right; 746 | position: relative; 747 | 748 | a { 749 | display: block; 750 | position: absolute; 751 | top: 3rem; 752 | right: 3rem; 753 | font-size: 1.2rem; 754 | } 755 | } 756 | 757 | } 758 | 759 | footer { 760 | 761 | z-index: 0; 762 | position: fixed; 763 | bottom: 0; 764 | left: 0; 765 | padding: 1rem; 766 | font-size: .9em; 767 | background: @aside-bg; 768 | border-top-right-radius: 3px; 769 | 770 | p { 771 | line-height: 1.5; 772 | padding: 0 5px 0 0; 773 | } 774 | 775 | dl { 776 | border-bottom: solid fade(@color-alpha, 50%) 1px; 777 | margin: 0 0 .5rem; 778 | padding: 0; 779 | 780 | dt { 781 | margin: 0; 782 | padding: 0 0 .5rem 16px; 783 | cursor: pointer; 784 | position: relative; 785 | font-weight: bold; 786 | color: @color-alpha; 787 | &:hover { color: @color-beta-light; } 788 | 789 | transition: color .25s ease-in-out; 790 | 791 | &:before { 792 | content: ''; 793 | display: block; 794 | position: absolute; 795 | top: 6px; 796 | left: 4px; 797 | width: 6px; 798 | height: 6px; 799 | 800 | border-top: solid 6px @color-fg; 801 | border-left: solid 3px transparent; 802 | border-right: solid 3px transparent; 803 | border-bottom: none; 804 | 805 | transition: transform .35s ease-in-out; 806 | transform-origin: center center; 807 | transform: rotate(-90deg); 808 | } 809 | 810 | &.visible:before { transform: rotate(0deg); } 811 | } 812 | dd { 813 | max-height: 0; 814 | overflow: hidden; 815 | transition: max-height .35s ease-in-out; 816 | 817 | pre { 818 | border: dotted @color-fg-dark 1px; 819 | margin: 0 0 1rem; 820 | padding: 0; 821 | 822 | > code { 823 | margin: 0; 824 | padding: 1rem; 825 | color: @color-fg-light; 826 | cursor: text; 827 | } 828 | } 829 | &.visible { max-height: 320px; } 830 | } 831 | } 832 | } 833 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CSS Transform Functions Visualizer 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 | 32 |
33 |

CSS3 Transform

34 |

2D & 3D CSS Transform functions visualizer

35 |
36 |
37 | 38 |
39 | 40 | × 41 |
42 | 43 | 221 | 222 |
223 |
224 |
225 |
Front
226 |
Back
227 |
228 |
229 |
230 |
231 | 232 |
233 |
234 |

Rotation (2D)

235 | 236 |

rotate() Rotates an element around a fixed point on the 2D plane.

237 |

The rotate() CSS function defines a transformation that rotates an element around a fixed point on the 2D plane, without deforming it. The amount of rotation created by rotate() is specified by an angle value expressed in degrees, gradians, radians, or turns. If positive, the movement will be clockwise; if negative, it will be counter-clockwise. (A rotation by 180° is called point reflection.)

238 |

The axis of rotation passes through an origin, defined by the transform-origin CSS property.

239 |

More info: developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotate

240 | 241 |
242 |
243 | 244 |
245 |

Rotation (3D)

246 | 247 |
248 | 249 |

rotateX() Rotates an element around the horizontal axis.

250 |
251 |

The rotateX() CSS function defines a transformation that rotates an element around the abscissa (horizontal axis) without deforming it. The amount of rotation created by rotateX() is specified by an angle value expressed in degrees, gradians, radians, or turns. If positive, the movement will be clockwise; if negative, it will be counter-clockwise.

252 |

The axis of rotation passes through an origin, defined by the transform-origin CSS property.

253 |

rotateX(a) is equivalent to rotate3d(1, 0, 0, a).

254 |

More info : developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotateX

255 |
256 |
257 | 258 |

rotateY() Rotates an element around the vertical axis.

259 |
260 |

The rotateY() CSS function defines a transformation that rotates an element around the ordinate (vertical axis) without deforming it. The amount of rotation created by rotateY() is specified by an angle value expressed in degrees, gradians, radians, or turns. If positive, the movement will be clockwise; if negative, it will be counter-clockwise.

261 |

The axis of rotation passes through an origin, defined by the transform-origin CSS property.

262 |

rotateY(a) is equivalent to rotate3d(0, 1, 0, a).

263 |

More info : developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotateY

264 |
265 |
266 | 267 |

rotateZ() Rotates an element around the z-axis.

268 |
269 |

The rotateZ() CSS function defines a transformation that rotates an element around the z-axis without deforming it.

270 |

The amount of rotation created by rotateZ() is specified by an angle value expressed in degrees, gradians, radians, or turns. If positive, the movement will be clockwise; if negative, it will be counter-clockwise.

271 |

The axis of rotation passes through an origin, defined by the transform-origin CSS property.

272 |

rotateZ(a) is equivalent to rotate(a) or rotate3d(0, 0, 1, a).

273 |

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotateZ

274 |
275 | 276 |
277 |
278 | 279 |
280 |

Perspective

281 | 282 |

perspective() Sets the distance between the user and the z=0 plane.

283 |

The perspective() CSS function defines a transformation that sets the distance between the user and the z=0 plane.

284 |

The perspective distance used by perspective() is specified by a length value (a number followed by a length unit: em, rem, px, pt, mm…), which represents the distance between the user and the z=0 plane. A positive value makes the element appear closer to the user, a negative value farther.

285 |

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/perspective

286 | 287 |
288 |
289 | 290 |
291 |

Transform Origin

292 | 293 |

transform-origin() Sets the origin for an element's transformations.

294 |

The transformation origin is the point around which a transformation is applied. For example, the transformation origin of the rotate() function is the center of rotation.

295 |

The transform-origin property may be specified using one, two, or three values, where each value represents an offset. Offsets that are not explicitly defined are reset to their corresponding initial values.

296 |

If two or more values are defined and either no value is a keyword, or the only used keyword is center, then the first value represents the horizontal offset and the second represents the vertical offset.

297 |
    298 |
  • One-value syntax: The value must be a length, a percentage, or one of the keywords left, center, right, top, and bottom.
  • 299 |
  • Two-value syntax: One value must be a length, a percentage, or one of the keywords left, center, and right. The other value must be a length, a percentage, or one of the keywords top, center, and bottom.
  • 300 |
  • Three-value syntax: The first two values are the same as for the two-value syntax. The third value must be a length. It always represents the Z offset.
  • 301 |
302 |

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin

303 | 304 |
305 |
306 | 307 | 308 |
309 |

Scaling (Resizing)

310 | 311 |
312 | 313 |

scale() Scales an element up or down on the 2D plane.

314 |
315 |

The scale() CSS function defines a transformation that resizes an element on the 2D plane. Because the amount of scaling is defined by a vector, it can resize the horizontal and vertical dimensions at different scales.

316 |

This scaling transformation is characterized by a two-dimensional vector. Its coordinates define how much scaling is done in each direction. If both coordinates are equal, the scaling is uniform (isotropic) and the aspect ratio of the element is preserved (this is a homothetic transformation).

317 |

When a coordinate value is outside the [-1, 1] range, the element grows along that dimension; when inside, it shrinks. If it is negative, the result a point reflection in that dimension. A value of 1 has no effect.

318 |

The scale() function only scales in 2D. To scale in 3D, use scale3d() instead.

319 |

The scale() function is specified with either one or two values, which represent the amount of scaling to be applied in each direction.

320 |
scale(sx)
321 | scale(sx, sy)
322 | /*
323 | - sx : A number representing the abscissa of the scaling vector.
324 | - sy : A number representing the ordinate of the scaling vector. If not defined, its default value is sx, resulting in a uniform scaling that preserves the element's aspect ratio.
325 | */
326 |

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scale

327 |
328 | 329 |
330 | 331 |

scaleX() Scales an element up or down horizontally.

332 |
333 |

The scaleX() CSS function defines a transformation that resizes an element along the x-axis (horizontally).

334 |

It modifies the abscissa of each element point by a constant factor, except when the scale factor is 1, in which case the function is the identity transform. The scaling is not isotropic, and the angles of the element are not conserved. scaleX(-1) defines an axial symmetry, with a vertical axis passing through the origin (as specified by the transform-origin property).

335 |

scaleX(sx) is equivalent to scale(sx, 1) or scale3d(sx, 1, 1).

336 |

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scaleX

337 |
338 | 339 |
340 | 341 |

scaleY() Scales an element up or down vertically.

342 |
343 |

The scaleY() CSS function defines a transformation that resizes an element along the y-axis (vertically).

344 |

It modifies the ordinate of each element point by a constant factor, except when the scale factor is 1, in which case the function is the identity transform. The scaling is not isotropic, and the angles of the element are not conserved. scaleY(-1) defines an axial symmetry, with a horizontal axis passing through the origin (as specified by the transform-origin property).

345 |

scaleY(sy) is equivalent to scale(1, sy) or scale3d(1, sy, 1).

346 |

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scaleY

347 |
348 | 349 |
350 |
351 | 352 |
353 |

Translation (Moving)

354 | 355 |
356 | 357 |

translate() Translates an element on the 2D plane.

358 |
359 |

The translate() CSS function repositions an element in the horizontal and/or vertical directions.

360 |

This transformation is characterized by a two-dimensional vector. Its coordinates define how much the element moves in each direction.

361 |

The translate() function is specified as either one or two values.

362 |
translate(tx)
363 | translate(tx, ty)
364 | /*
365 | - tx : Is a length value representing the abscissa (x-coordinate) of the translating vector.
366 | - ty : Is a length value representing the ordinate of the translating vector (or y-coordinate). If unspecified, its default value is 0. For example, translate(2) is equivalent to translate(2, 0).
367 | */
368 |

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translate

369 |
370 | 371 |
372 | 373 |

translateX() Translates an element horizontally.

374 |
375 |

The translateX() CSS function repositions an element horizontally on the 2D plane.

376 |

Syntax : translateX(t). (t is a length value representing the abscissa of the translating vector.)

377 |

translateX(tx) is equivalent to translate(tx, 0) or translate3d(tx, 0, 0).

378 |

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translateX

379 |
380 | 381 |
382 | 383 |

translateY() Translates an element vertically.

384 |
385 |

The translateY() CSS function repositions an element vertically on the 2D plane.

386 |

translateY(ty) is equivalent to translate(0, ty) or translate3d(0, ty, 0).

387 |

Syntax : translateY(t). (t is a length value representing the ordinate of the translating vector.)

388 |

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translateY

389 |
390 |
391 |
392 | 393 |
394 |

Skewing (Distortion)

395 | 396 |
397 | 398 |

skew() Skews an element on the 2D plane.

399 |
400 |

The skew() CSS function defines a transformation that skews an element on the 2D plane.

401 |

This transformation is a shear mapping (transvection) that distorts each point within an element by a certain angle in the horizontal and vertical directions. The coordinates of each point are modified by a value proportionate to the specified angle and the distance to the origin; thus, the farther from the origin a point is, the greater will be the value added it.

402 |

The skew() function is specified with either one or two values, which represent the amount of skewing to be applied in each direction.

403 |
skew(ax)
404 | skew(ax, ay)
405 | /*
406 | - ax : Is an angle value expressed in degrees, gradians, radians, or turns; representing the angle to use to distort the element along the abscissa.
407 | - ay : Is an angle value expressed in degrees, gradians, radians, or turns; representing the angle to use to distort the element along the ordinate. If not defined, its default value is 0, resulting in a purely horizontal skewing.
408 | */
409 |

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/skew

410 |
411 |
412 | 413 |

skewX() : Skews an element in the horizontal direction.

414 |
415 |

The skewX() CSS function defines a transformation that skews an element in the horizontal direction on the 2D plane.

416 |

This transformation is a shear mapping (transvection) that distorts each point within an element by a certain angle in the horizontal direction. The abscissa coordinate of each point is modified by a value proportionate to the specified angle and the distance to the origin; thus, the farther from the origin a point is, the greater will be the value added it.

417 |

skewX(a) is equivalent to skew(a).

418 |

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/skewX

419 |
420 |
421 | 422 |

skewY() Skews an element in the vertical direction.

423 |
424 |

The skewY() CSS function defines a transformation that skews an element in the vertical direction on the 2D plane.

425 |

This transformation is a shear mapping (transvection) that distorts each point within an element by a certain angle in the vertical direction. The ordinate coordinate of each point is modified by a value proportionate to the specified angle and the distance to the origin; thus, the farther from the origin a point is, the greater will be the value added it.

426 |

More Info : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/skewY

427 |
428 | 429 |
430 |
431 | 432 |

Close

433 |
434 | 435 |
436 |
437 |
CSS Output
438 |
439 |
{{ styleObject | stringOutput }}
440 |
element {
441 |     /* No styling applied yet */
442 | }
443 |
444 |
445 |

446 | A project created by Jorge Moreno @alterebro 447 |
Source Code on GitHub — © 2019 www.moro.es 448 |

449 |
450 |
451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | -------------------------------------------------------------------------------- /src/js/app.js: -------------------------------------------------------------------------------- 1 | 2 | const randomInt = function(min, max) { 3 | // Returns a random integer between @min and @max (inclusive) 4 | let _max = parseInt(max); 5 | let _min = parseInt(min); 6 | return Math.floor(Math.random() * ((_max - _min) + 1)) + _min; 7 | } 8 | 9 | const Data = { 10 | 11 | rotate2Dactive : false, 12 | rotate2D : 10, 13 | 14 | rotate3Dactive : false, 15 | rotateX : 10, 16 | rotateY : 10, 17 | rotateZ : 0, 18 | 19 | perspectiveActive : false, 20 | perspective : 700, 21 | 22 | transformOriginActive : false, 23 | transformOriginX : 50, 24 | transformOriginY : 50, 25 | transformOriginZ : -70, 26 | 27 | scaleActive : false, 28 | scale : 1, 29 | 30 | translateActive : false, 31 | translateX : -10, 32 | translateY : -20, 33 | 34 | skewActive : false, 35 | skewX : 10, 36 | skewY : 10, 37 | 38 | modal : { 39 | visible : false, 40 | current : null 41 | }, 42 | 43 | sidebar : false, 44 | cssOutput : false 45 | } 46 | 47 | const App = new Vue({ 48 | 49 | el : '#app', 50 | data : Data, 51 | 52 | mounted() { 53 | 54 | let infoSections = Array.from( document.querySelectorAll('#app > article section') ); 55 | infoSections.forEach( (el) => { 56 | el.addEventListener('click', (e) => e.stopPropagation() ); 57 | }); 58 | 59 | let infoTriggers = Array.from( document.querySelectorAll('#app > aside dl dt a') ); 60 | infoTriggers.forEach( (el) => { 61 | 62 | el.addEventListener('click', (e) => { 63 | e.preventDefault(); 64 | 65 | let _current = el.href.split('#')[1]; 66 | this.modal.current = _current; 67 | infoSections.forEach( (el) => el.style.display = 'none' ); 68 | document.querySelector( `#app > article section#${_current}`).style.display = 'block'; 69 | 70 | this.modalWindowShow(); 71 | }); 72 | }); 73 | 74 | // Modal window close handlers 75 | let infoCloser = document.querySelector('#app > article > p a'); 76 | infoCloser.addEventListener('click', (e) => { 77 | e.preventDefault(); 78 | this.modalWindowHide(); 79 | }); 80 | document.querySelector('#app > article').addEventListener('click', () => this.modalWindowHide() ); 81 | 82 | // Init (close) 83 | this.modalWindowHide() 84 | 85 | // Some keyboard action 86 | document.addEventListener('keyup', e => { 87 | 88 | if ( e.keyCode === 27 ) { this.modalWindowHide() } // 'Esc' to close modal 89 | if ( e.keyCode === 9 ) { this.sidebar = !this.sidebar } // 'Tab' to toggle Sidebar 90 | if ( e.keyCode === 32 ) { this.toggleCSSOutput() } // 'Space' to toggle CSS Output 91 | 92 | if ( e.keyCode === 49 ) { this.randomAll() } // Num key 1 93 | if ( e.keyCode === 50 ) { this.resetAll() } // Num key 2 94 | if ( e.keyCode === 51 ) { this.activateAll(true) } // Num key 3 95 | if ( e.keyCode === 52 ) { this.activateAll(false) } // Num key 4 96 | }) 97 | 98 | // Accordion 99 | // TODO : Close when only one is open 100 | let detailsBlocks = Array.from( document.querySelectorAll('#app > article > section details summary') ); 101 | detailsBlocks.forEach( (el) => { 102 | 103 | el.addEventListener('click', (e) => { 104 | 105 | e.preventDefault(); 106 | let _detailsChildren = Array.from( el.parentNode.parentNode.querySelectorAll('details') ); 107 | _detailsChildren.forEach( (_el) => _el.removeAttribute('open') ); 108 | el.parentNode.setAttribute('open', ''); 109 | }); 110 | }); 111 | 112 | 113 | // INTRO 114 | // Chain of Actions 115 | let actionsChain = 116 | chainTimeout( () => this.cssOutput = true, 250 ) 117 | .chainTimeout( () => { 118 | this.transformOriginActive = true; 119 | this.rotate2Dactive = true; 120 | }, 250 ) 121 | .chainTimeout( () => this.rotate3Dactive = true, 500 ) 122 | .chainTimeout( () => this.rotateZ = 10, 500 ) 123 | .chainTimeout( () => this.perspectiveActive = true, 500 ) 124 | .chainTimeout( () => { 125 | this.perspective = 1500; 126 | this.rotateZ = -45; 127 | }, 500 ) 128 | .chainTimeout( () => { 129 | this.scaleActive = true; 130 | this.scale = 0.8; 131 | }, 500 ) 132 | .chainTimeout( () => this.translateActive = true, 500 ) 133 | .chainTimeout( () => this.skewActive = true, 500 ) 134 | .chainTimeout( () => { 135 | this.rotateY = 40; 136 | this.rotateZ = 0; 137 | this.perspective = 800; 138 | this.scale = 0.9; 139 | this.translateX = -50; 140 | this.translateY = 0; 141 | this.skewX = 0; 142 | this.skewY = 0; 143 | }, 500 ) 144 | .chainTimeout( () => this.sidebar = true , 500 ) 145 | .chainTimeout( () => this.cssOutput = false , 250 ) 146 | .chainTimeout( () => this.resetAll() , 250 ) 147 | .chainTimeout( () => this.sidebar = false , 1000 ) 148 | 149 | // ----- 150 | // Info dialog on the console 151 | let keyCommands = [ 152 | ' • Esc : Closes info modal window when opened.', 153 | ' • Tab : Open / closes the sidebar.', 154 | ' • Space : Open / closes the CSS Output footer panel.', 155 | ' • Num. #1 : Random All transform functions.', 156 | ' • Num. #2 : Reset All transform functions.', 157 | ' • Num. #3 : Activate All transform functions.', 158 | ' • Num. #4 : Deactivate All transform functions.', 159 | ]; 160 | 161 | console.log( 162 | '\n' + 163 | '%ccss-transform' + 164 | '%c\nKeyboard commands:' + 165 | '%c\n' + keyCommands.join("\n") + 166 | '%c\n@alterebro - https://twitter.com/alterebro' + 167 | '\n', 168 | 169 | 'color: #fff; background-color: #444; padding: 5px 10px; margin: 10px 0 5px; border-radius: 3px;', 170 | 'font-weight: bold; margin: 5px; display: block;', 171 | 'line-height: 1.5; font-family: monospace; color: #217eaa', 172 | 'margin: 5px 10px; display: block; font-size: 90%; color: #777' 173 | ); 174 | }, 175 | 176 | computed : { 177 | 178 | styleObject() { 179 | 180 | const _styles = { 181 | 'transform' : [], 182 | 'transform-origin' : null 183 | }; 184 | 185 | let _trFunctions = []; 186 | 187 | // Rotate 2D 188 | if ( this.rotate2D != 0 && this.rotate2D != 360 && this.rotate2Dactive ) { _trFunctions.push( 'rotate('+this.rotate2D + 'deg)' ) } 189 | 190 | // Rotate 3D 191 | if ( this.rotate3Dactive ) { 192 | if ( this.rotateX && this.rotateX != 0 ) { _trFunctions.push( 'rotateX('+this.rotateX + 'deg)' ) } 193 | if ( this.rotateY && this.rotateY != 0 ) { _trFunctions.push( 'rotateY('+this.rotateY + 'deg)' ) } 194 | if ( this.rotateZ && this.rotateZ != 0 ) { _trFunctions.push( 'rotateZ('+this.rotateZ + 'deg)' ) } 195 | } 196 | 197 | // Perspective 198 | if ( this.perspectiveActive ) { _trFunctions.push( 'perspective('+this.perspective + 'px)' ) } 199 | 200 | // Scale 201 | if ( this.scaleActive && this.scale != 1 ) { _trFunctions.push('scale('+this.scale+')') } 202 | 203 | // Translate 204 | if ( this.translateActive && (this.translateX !=0 || this.translateY !=0) ) { _trFunctions.push('translate('+this.translateX+'px,'+this.translateY+'px)') } 205 | 206 | // Skew 207 | if ( this.skewActive && (this.skewX !=0 || this.skewY !=0) ) { _trFunctions.push('skew('+this.skewX+'deg,'+this.skewY+'deg)') } 208 | 209 | _styles['transform'] = _trFunctions; 210 | 211 | 212 | if ( this.transformOriginActive ) { 213 | 214 | let _x = { 0 : 'left', 50 : 'center', 100 : 'right' }; 215 | let _y = { 0 : 'top', 50 : 'center', 100 : 'bottom' }; 216 | 217 | let origin_x = ( this.transformOriginX == 0 || this.transformOriginX == 50 || this.transformOriginX == 100 ) 218 | ? _x[this.transformOriginX] 219 | : this.transformOriginX+'%'; 220 | 221 | let origin_y = ( this.transformOriginY == 0 || this.transformOriginY == 50 || this.transformOriginY == 100 ) 222 | ? _y[this.transformOriginY] 223 | : this.transformOriginY+'%'; 224 | 225 | let output = origin_x + ' ' + origin_y; 226 | output = ( this.transformOriginZ && this.transformOriginZ != 0 ) ? output + ' ' + this.transformOriginZ + 'px' : output; 227 | 228 | _styles['transform-origin'] = output; 229 | } 230 | 231 | return _styles; 232 | }, 233 | 234 | styleClass() { 235 | return { 236 | 'transform' : this.styleObject.transform.join(' '), 237 | 'transformOrigin' : (this.styleObject['transform-origin']) ? this.styleObject['transform-origin'] : '' 238 | } 239 | }, 240 | 241 | hasStyle() { 242 | return (this.styleObject.transform.length > 0) || (this.styleObject['transform-origin'] != null); 243 | }, 244 | 245 | isActivated() { 246 | return !( 247 | this.transformOriginActive == false && 248 | this.rotate2Dactive == false && 249 | this.rotate3Dactive == false && 250 | this.perspectiveActive == false && 251 | this.scaleActive == false && 252 | this.translateActive == false && 253 | this.skewActive == false 254 | ); 255 | }, 256 | 257 | }, 258 | 259 | filters : { 260 | 261 | stringOutput(obj) { 262 | 263 | let _output = []; 264 | 265 | if ( !!obj['transform'].length ) { _output.push( `transform: ${obj['transform'].join('\n\t\t')};` ) } 266 | if ( !!obj['transform-origin'] ) { _output.push( `transform-origin: ${obj['transform-origin']};` ) } 267 | 268 | return (_output.length) ? `element {\n\t${_output.join('\n\t')}\n}` : ''; 269 | } 270 | 271 | }, 272 | 273 | methods : { 274 | 275 | // ------------------ 276 | // - Modal Info Window 277 | modalWindowShow() { 278 | let _modal = document.querySelector('#app > article'); 279 | _modal.classList.remove('gone'); 280 | chainTimeout( () => _modal.classList.add('visible'), 10 ); 281 | }, 282 | modalWindowHide() { 283 | let _modal = document.querySelector('#app > article'); 284 | _modal.classList.remove('visible'); 285 | chainTimeout( () => _modal.classList.add('gone'), 350 ); 286 | }, 287 | 288 | // ------------------ 289 | // - Sidebar 290 | openSidebar() { this.sidebar = true }, 291 | closeSidebar() { this.sidebar = false }, 292 | 293 | // ------------------ 294 | // - CSS Output 295 | toggleCSSOutput() { this.cssOutput = !this.cssOutput }, 296 | 297 | // ------------------ 298 | // - Transform Functions 299 | 300 | // Rotate 2D 301 | randomRotate2D() { this.rotate2D = randomInt(0, 359) }, 302 | resetRotate2D() { this.rotate2D = 0 }, 303 | 304 | // Rotate 3D 305 | randomRotate3D() { 306 | this.rotateX = randomInt(0, 359); 307 | this.rotateY = randomInt(0, 359); 308 | this.rotateZ = randomInt(0, 359); 309 | }, 310 | resetRotate3D() { this.rotateX = this.rotateY = this.rotateZ = 0; }, 311 | 312 | // Perspective 313 | randomPerspective() { this.perspective = (randomInt(3, 23) * 100) }, 314 | resetPerspective() { this.perspective = 700 }, 315 | 316 | // Transform Origin 317 | randomTransformOrigin() { 318 | this.transformOriginX = randomInt(0, 100); 319 | this.transformOriginY = randomInt(0, 100); 320 | this.transformOriginZ = randomInt(-250, 250); 321 | }, 322 | resetTransformOrigin() { 323 | this.transformOriginX = this.transformOriginY = 50; 324 | this.transformOriginZ = 0; 325 | }, 326 | 327 | // Scale 328 | randomScale() { this.scale = (randomInt(5, 20) / 10) }, 329 | resetScale() { this.scale = 1; }, 330 | 331 | // Translate 332 | randomTranslate() { 333 | this.translateX = (randomInt(-10, 10) * 10); 334 | this.translateY = (randomInt(-10, 10) * 10); 335 | }, 336 | resetTranslate() { this.translateX = this.translateY = 0 }, 337 | 338 | // Skew 339 | randomSkew() { 340 | this.skewX = randomInt(0, 180); 341 | this.skewY = randomInt(0, 180); 342 | }, 343 | resetSkew() { this.skewX = this.skewY = 0 }, 344 | 345 | // ------------------ 346 | // - Multiple Transform Action 347 | randomAll : function() { 348 | this.randomTransformOrigin(); 349 | this.randomRotate2D(); 350 | this.randomRotate3D(); 351 | this.randomPerspective(); 352 | this.randomScale(); 353 | this.randomTranslate(); 354 | this.randomSkew(); 355 | }, 356 | resetAll : function() { 357 | this.resetTransformOrigin(); 358 | this.resetRotate2D(); 359 | this.resetRotate3D(); 360 | this.resetPerspective(); 361 | this.resetScale(); 362 | this.resetTranslate(); 363 | this.resetSkew(); 364 | }, 365 | activateAll : function(seriously) { this.transformOriginActive = this.rotate2Dactive = this.rotate3Dactive = this.perspectiveActive = this.scaleActive = this.translateActive = this.skewActive = seriously } 366 | 367 | } 368 | 369 | }); 370 | -------------------------------------------------------------------------------- /src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "CSS Transform Playground", 3 | "short_name": "css-transform", 4 | "lang": "en-US", 5 | "start_url": "/index.html?launcher=true", 6 | "display": "fullscreen", 7 | "orientation": "any", 8 | "theme_color": "#1a1718" 9 | } 10 | --------------------------------------------------------------------------------