Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <div id="app" v-bind:class="{ 'with-sidebar' : sidebar }">

    <header>
        <h1><a href="https://css-transform.moro.es">CSS3 Transform</a></h1>
        <p>2D &amp; 3D CSS Transform functions visualizer</p>
        <hr />
    </header>

    <section id="do">
        <a id="open" @click.prevent="openSidebar" href="#sidebar"><em>&#x2261;</em></a>
        <a id="close" @click.prevent="closeSidebar" href="#main"><em>&times;</em></a>
    </section>

    <aside id="sidebar">
        <form action="/" method="post">
            <fieldset>
                <legend>Property Settings</legend>
                <dl>

                    <!-- Rotate 2D -->
                    <dt>
                        <label for="rotate-2d" class="checkboxed">
                            <input type="checkbox" id="rotate-2d" v-model="rotate2Dactive" />
                            <strong>Rotate 2D</strong>
                        </label>
                        <a href="#info-rotate-2d">Info</a>
                    </dt>
                    <dd>
                        <label for="rotate-2d-range">rotate (2D)</label>
                        <input type="range" id="rotate-2d-range" v-model="rotate2D" min="0" max="359" step="1" />
                        <code v-text="rotate2D + 'deg'">&mdash;</code>
                    </dd>
                    <dd class="buttons">
                        <button type="button" @click="randomRotate2D" class="btn-random">Random</button>
                        <button type="button" @click="resetRotate2D" class="btn-reset">Reset</button>
                    </dd>

                    <!-- Rotate 3D -->
                    <dt>
                        <label for="rotate-3d" class="checkboxed">
                            <input type="checkbox" id="rotate-3d" v-model="rotate3Dactive" />
                            <strong>Rotate 3D</strong>
                        </label>
                        <a href="#info-rotate-3d">Info</a>
                    </dt>
                    <dd>
                        <label for="rotate-3d-range-x">rotate (x)</label>
                        <input type="range" id="rotate-3d-range-x" v-model="rotateX" min="0" max="359" step="1" />
                        <code v-text="rotateX + 'deg'">&mdash;</code>
                    </dd>
                    <dd>
                        <label for="rotate-3d-range-y">rotate (y)</label>
                        <input type="range" id="rotate-3d-range-y" v-model="rotateY" min="0" max="359" step="1" />
                        <code v-text="rotateY + 'deg'">&mdash;</code>
                    </dd>
                    <dd>
                        <label for="rotate-3d-range-z">rotate (z)</label>
                        <input type="range" id="rotate-3d-range-z" v-model="rotateZ" min="0" max="359" step="1" />
                        <code v-text="rotateZ + 'deg'">&mdash;</code>
                    </dd>
                    <dd class="buttons">
                        <button type="button" @click="randomRotate3D" class="btn-random">Random</button>
                        <button type="button" @click="resetRotate3D" class="btn-reset">Reset</button>
                    </dd>

                    <!-- Perspective -->
                    <dt>
                        <label for="perspective" class="checkboxed">
                            <input type="checkbox" id="perspective" v-model="perspectiveActive" />
                            <strong>Perspective</strong>
                        </label>
                        <a href="#info-perspective">Info</a>
                    </dt>
                    <dd>
                        <label for="perspective-range">perspective</label>
                        <input type="range" id="perspective-range" v-model="perspective" min="300" max="2300" step="100" />
                        <code v-text="perspective">&mdash;</code>
                    </dd>
                    <dd class="buttons">
                        <button type="button" @click="randomPerspective" class="btn-random">Random</button>
                        <button type="button" @click="resetPerspective" class="btn-reset">Reset</button>
                    </dd>

                    <!-- Transform Origin -->
                    <dt>
                        <label for="transform-origin" class="checkboxed">
                            <input type="checkbox" id="transform-origin" v-model="transformOriginActive" />
                            <strong>Transform Origin</strong>
                        </label>
                        <a href="#info-transform-origin">Info</a>
                    </dt>
                    <dd>
                        <label for="transform-x-range">transform-origin (x)</label>
                        <input type="range" id="transform-x-range" v-model="transformOriginX" min="0" max="100" step="1" />
                        <code v-text="transformOriginX + '%'">&mdash;</code>
                    </dd>
                    <dd>
                        <label for="transform-y-range">transform-origin (y)</label>
                        <input type="range" id="transform-y-range" v-model="transformOriginY" min="0" max="100" step="1" />
                        <code v-text="transformOriginY + '%'">&mdash;</code>
                    </dd>
                    <dd>
                        <label for="transform-z-range">transform-origin (z)</label>
                        <input type="range" id="transform-z-range" v-model="transformOriginZ" min="-250" max="250" step="10" />
                        <code v-text="transformOriginZ + 'px'">&mdash;</code>
                    </dd>
                    <dd class="buttons">
                        <button type="button" @click="randomTransformOrigin" class="btn-random">Random</button>
                        <button type="button" @click="resetTransformOrigin" class="btn-reset">Reset</button>
                    </dd>

                    <!-- Scale -->
                    <dt>
                        <label for="scale" class="checkboxed">
                            <input type="checkbox" id="scale" v-model="scaleActive" />
                            <strong>Scale</strong>
                        </label>
                        <a href="#info-scale">Info</a>
                    </dt>
                    <dd>
                        <label for="scale-range">scale</label>
                        <input type="range" id="scale-range" v-model="scale" min="0.5" max="2" step=".1" />
                        <code v-text="scale">&mdash;</code>
                    </dd>
                    <dd class="buttons">
                        <button type="button" @click="randomScale" class="btn-random">Random</button>
                        <button type="button" @click="resetScale" class="btn-reset">Reset</button>
                    </dd>

                    <!-- Translate -->
                    <dt>
                        <label for="translate" class="checkboxed">
                            <input type="checkbox" id="translate" v-model="translateActive" />
                            <strong>Translate</strong>
                        </label>
                        <a href="#info-translate">Info</a>
                    </dt>
                    <dd>
                        <label for="translate-x-range">translate-x</label>
                        <input type="range" id="translate-x-range" v-model="translateX" min="-100" max="100" step="10" />
                        <code v-text="translateX">&mdash;</code>
                    </dd>
                    <dd>
                        <label for="translate-y-range">translate-y</label>
                        <input type="range" id="translate-y-range" v-model="translateY" min="-100" max="100" step="10" />
                        <code v-text="translateY">&mdash;</code>
                    </dd>
                    <dd class="buttons">
                        <button type="button" @click="randomTranslate" class="btn-random">Random</button>
                        <button type="button" @click="resetTranslate" class="btn-reset">Reset</button>
                    </dd>

                    <!-- Skew -->
                    <dt>
                        <label for="skew" class="checkboxed">
                            <input type="checkbox" id="skew" v-model="skewActive" />
                            <strong>Skew</strong>
                        </label>
                        <a href="#info-skew">Info</a>
                    </dt>
                    <dd>
                        <label for="skew-x-range">skew-x</label>
                        <input type="range" id="skew-x-range" v-model="skewX" min="0" max="180" step="1" />
                        <code v-text="skewX">&mdash;</code>
                    </dd>
                    <dd>
                        <label for="skew-y-range">skew-y</label>
                        <input type="range" id="skew-y-range" v-model="skewY" min="0" max="180" step="1" />
                        <code v-text="skewY">&mdash;</code>
                    </dd>
                    <dd class="buttons">
                        <button type="button" @click="randomSkew" class="btn-random">Random</button>
                        <button type="button" @click="resetSkew" class="btn-reset">Reset</button>
                    </dd>
                </dl>
            </fieldset>

            <hr />

            <fieldset>
                <legend>All Elements</legend>
                <p>
                    <button type="button" @click="randomAll" class="btn-random">Random</button>
                    <button type="button" @click="resetAll" class="btn-reset">Reset</button>
                    <button type="button" @click="activateAll(true)" class="btn-on">Activate</button>
                    <button type="button" @click="activateAll(false)" class="btn-off">Deactivate</button>
                </p>
            </fieldset>
        </form>
        <hr />
    </aside>

    <main id="main">
        <div id="box">
            <div id="alpha" v-bind:style="{ 'transform' : styleClass.transform, 'transform-origin' : styleClass.transformOrigin }">
                <div class="alpha-panel" v-bind:class="{ 'active' : isActivated }" id="alpha-front"><strong>Front</strong></div>
                <div class="alpha-panel" v-bind:class="{ 'active' : isActivated }" id="alpha-back"><strong>Back</strong></div>
            </div>
        </div>
        <hr />
    </main>

    <article>
        <section id="info-rotate-2d">
            <h2>Rotation (2D)</h2>

            <h3><code>rotate()</code> <small>Rotates an element around a fixed point on the 2D plane.</small></h3>
            <p>The <code>rotate()</code> 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 <code>rotate()</code> is specified by an <em>angle value</em> 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.)</p>
            <p>The axis of rotation passes through an origin, defined by the <code>transform-origin</code> CSS property.</p>
            <p> &mdash; <em>More info: <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotate" target="_blank">developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotate</a></em></p>

            <hr />
        </section>

        <section id="info-rotate-3d">
            <h2>Rotation (3D)</h2>

            <details open>
                <summary>
                    <h3><code>rotateX()</code> <small>Rotates an element around the horizontal axis.</small></h3>
                </summary>
                <p>The <code>rotateX()</code> CSS function defines a transformation that rotates an element around the abscissa (horizontal axis) without deforming it. The amount of rotation created by <code>rotateX()</code> is specified by an <em>angle value</em> expressed in degrees, gradians, radians, or turns. If positive, the movement will be clockwise; if negative, it will be counter-clockwise.</p>
                <p>The axis of rotation passes through an origin, defined by the transform-origin CSS property.</p>
                <blockquote><p><em><code>rotateX(a)</code> is equivalent to <code>rotate3d(1, 0, 0, a)</code>.</em></p></blockquote>
                <p> &mdash; <em>More info : <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotateX" target="_blank">developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotateX</a></em></p>
            </details>
            <details>
                <summary>
                    <h3><code>rotateY()</code> <small>Rotates an element around the vertical axis.</small></h3>
                </summary>
                <p>The <code>rotateY()</code> 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 <em>angle value</em> expressed in degrees, gradians, radians, or turns. If positive, the movement will be clockwise; if negative, it will be counter-clockwise.</p>
                <p>The axis of rotation passes through an origin, defined by the transform-origin CSS property.</p>
                <blockquote><p><em><code>rotateY(a)</code> is equivalent to <code>rotate3d(0, 1, 0, a)</code>.</em></p></blockquote>
                <p> &mdash; <em>More info : <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotateY" target="_blank">developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotateY</a></em></p>
            </details>
            <details>
                <summary>
                    <h3><code>rotateZ()</code> <small>Rotates an element around the z-axis.</small></h3>
                </summary>
                <p>The <code>rotateZ()</code> CSS function defines a transformation that rotates an element around the z-axis without deforming it.</p>
                <p>The amount of rotation created by rotateZ() is specified by an <em>angle value</em> expressed in degrees, gradians, radians, or turns. If positive, the movement will be clockwise; if negative, it will be counter-clockwise.</p>
                <p>The axis of rotation passes through an origin, defined by the transform-origin CSS property.</p>
                <blockquote><p><em><code>rotateZ(a)</code> is equivalent to <code>rotate(a)</code> or <code>rotate3d(0, 0, 1, a)</code>.</em></p></blockquote>
                <p> &mdash; <em>More Info : <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotateZ" target="_blank">https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotateZ</a></em></p>
            </details>

            <hr />
        </section>

        <section id="info-perspective">
            <h2>Perspective</h2>

            <h3><code>perspective()</code> <small>Sets the distance between the user and the z=0 plane.</small></h3>
            <p>The <code>perspective()</code> CSS function defines a transformation that sets the distance between the user and the z=0 plane.</p>
            <p>The perspective distance used by <code>perspective()</code> is specified by a <em><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/length">length</a></em> value (a number followed by a length unit: em, rem, px, pt, mm&hellip;), 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.</p>
            <p> &mdash; <em>More Info : <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/perspective" target="_blank">https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/perspective</a></em></p>

            <hr />
        </section>

        <section id="info-transform-origin">
            <h2>Transform Origin</h2>

            <h3><code>transform-origin()</code> <small>Sets the origin for an element's transformations.</small></h3>
            <p>The transformation origin is the point around which a transformation is applied. For example, the transformation origin of the <code>rotate()</code> function is the center of rotation.</p>
            <p>The <code>transform-origin</code> 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.</p>
            <p>If two or more values are defined and either no value is a keyword, or the only used keyword is <code>center</code>, then the first value represents the horizontal offset and the second represents the vertical offset.</p>
            <ul>
                <li><strong>One-value syntax:</strong> The value must be a <em>length</em>, a <em>percentage</em>, or one of the keywords <code>left</code>, <code>center</code>, <code>right</code>, <code>top</code>, and <code>bottom</code>.</li>
                <li><strong>Two-value syntax:</strong> One value must be a <em>length</em>, a <em>percentage</em>, or one of the keywords <code>left</code>, <code>center</code>, and <code>right</code>. The other value must be a <em>length</em>, a <em>percentage</em>, or one of the keywords <code>top</code>, <code>center</code>, and <code>bottom</code>.</li>
                <li><strong>Three-value syntax:</strong> The first two values are the same as for the two-value syntax. The third value must be a <em>length</em>. It always represents the <code>Z offset</code>.</li>
            </ul>
            <p> &mdash; <em>More Info : <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin" target="_blank">https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin</a></em></p>

            <hr />
        </section>


        <section id="info-scale">
            <h2>Scaling (Resizing)</h2>

            <details open>
                <summary>
                    <h3><code>scale()</code> <small>Scales an element up or down on the 2D plane.</small></h3>
                </summary>
                <p>The <code>scale()</code> 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.</p>
                <p>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).</p>
                <p>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.</p>
                <blockquote><p><em>The <code>scale()</code> function only scales in 2D. To scale in 3D, use <code>scale3d()</code> instead.</em></p></blockquote>
                <p>The <code>scale()</code> function is specified with either one or two values, which represent the amount of scaling to be applied in each direction.</p>
<div><pre><code class="language-css">scale(sx)
scale(sx, sy)
/*
- sx : A number representing the abscissa of the scaling vector.
- 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&#39;s aspect ratio.
*/</code></pre></div>
                <p> &mdash; <em>More Info : <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scale" target="_blank">https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scale</a></em></p>
            </details>

            <details>
                <summary>
                    <h3><code>scaleX()</code> <small>Scales an element up or down horizontally.</small></h3>
                </summary>
                <p>The <code>scaleX()</code> CSS function defines a transformation that resizes an element along the x-axis (horizontally).</p>
                <p>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 <code>transform-origin</code> property).</p>
                <blockquote><p><em><code>scaleX(sx)</code> is equivalent to <code>scale(sx, 1)</code> or <code>scale3d(sx, 1, 1)</code>.</em></p></blockquote>
                <p> &mdash; <em>More Info : <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scaleX" target="_blank">https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scaleX</a></em></p>
            </details>

            <details>
                <summary>
                    <h3><code>scaleY()</code> <small>Scales an element up or down vertically.</small></h3>
                </summary>
                <p>The <code>scaleY()</code> CSS function defines a transformation that resizes an element along the y-axis (vertically).</p>
                <p>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).</p>
                <blockquote><p><em><code>scaleY(sy)</code> is equivalent to <code>scale(1, sy)</code> or <code>scale3d(1, sy, 1)</code>.</em></p></blockquote>
                <p> &mdash; <em>More Info : <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scaleY" target="_blank">https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scaleY</a></em></p>
            </details>

            <hr />
        </section>

        <section id="info-translate">
            <h2>Translation (Moving)</h2>

            <details open>
                <summary>
                    <h3><code>translate()</code> <small>Translates an element on the 2D plane.</small></h3>
                </summary>
                <p>The <code>translate()</code> CSS function repositions an element in the horizontal and/or vertical directions.</p>
                <p>This transformation is characterized by a two-dimensional vector. Its coordinates define how much the element moves in each direction.</p>
                <p>The <code>translate()</code> function is specified as either one or two values.</p>
<div><pre><code class="language-css">translate(tx)
translate(tx, ty)
/*
- tx : Is a length value representing the abscissa (x-coordinate) of the translating vector.
- 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).
*/</code></pre></div>
                <p> &mdash; <em>More Info : <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translate" target="_blank">https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translate</a></em></p>
            </details>

            <details>
                <summary>
                    <h3><code>translateX()</code> <small>Translates an element horizontally.</small></h3>
                </summary>
                <p>The <code>translateX()</code> CSS function repositions an element horizontally on the 2D plane.</p>
                <p>Syntax : <code>translateX(t)</code>. <em>(<code>t</code> is a length value representing the abscissa of the translating vector.)</em></p>
                <blockquote><p><code>translateX(tx)</code> is equivalent to <code>translate(tx, 0)</code> or <code>translate3d(tx, 0, 0)</code>.</p></blockquote>
                <p> &mdash; <em>More Info : <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translateX" target="_blank">https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translateX</a></em></p>
            </details>

            <details>
                <summary>
                    <h3><code>translateY()</code> <small>Translates an element vertically.</small></h3>
                </summary>
                <p>The <code>translateY()</code> CSS function repositions an element vertically on the 2D plane. </p>
                <blockquote><p><code>translateY(ty)</code> is equivalent to <code>translate(0, ty)</code> or <code>translate3d(0, ty, 0)</code>.</p></blockquote>
                <p>Syntax : <code>translateY(t)</code>. <em>(<code>t</code> is a length value representing the ordinate of the translating vector.)</em></p>
                <p> &mdash; <em>More Info : <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translateY" target="_blank">https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translateY</a></em></p>
            </details>
            <hr />
        </section>

        <section id="info-skew">
            <h2>Skewing (Distortion)</h2>

            <details open>
                <summary>
                    <h3><code>skew()</code> <small>Skews an element on the 2D plane.</small></h3>
                </summary>
                <p>The skew() CSS function defines a transformation that skews an element on the 2D plane.</p>
                <p>This transformation is a shear mapping (<a href="https://en.wikipedia.org/wiki/Shear_mapping" target="_blank">transvection</a>) 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.</p>
                <p>The skew() function is specified with either one or two values, which represent the amount of skewing to be applied in each direction.</p>
<div><pre><code class="language-css">skew(ax)
skew(ax, ay)
/*
- ax : Is an angle value expressed in degrees, gradians, radians, or turns; representing the angle to use to distort the element along the abscissa.
- 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.
*/</code></pre></div>
                <p> &mdash; <em>More Info : <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/skew" target="_blank">https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/skew</a></em></p>
            </details>
            <details>
                <summary>
                    <h3><code>skewX()</code> : <small>Skews an element in the horizontal direction.</small></h3>
                </summary>
                <p>The skewX() CSS function defines a transformation that skews an element in the horizontal direction on the 2D plane.</p>
                <p>This transformation is a shear mapping (<a href="https://en.wikipedia.org/wiki/Shear_mapping">transvection</a>) 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.</p>
                <blockquote><p><em><code>skewX(a)</code> is equivalent to <code>skew(a)</code>.</em></p></blockquote>
                <p> &mdash; <em>More Info : <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/skewX" target="_blank">https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/skewX</a></em></p>
            </details>
            <details>
                <summary>
                    <h3><code>skewY()</code> <small>Skews an element in the vertical direction.</small></h3>
                </summary>
                <p>The skewY() CSS function defines a transformation that skews an element in the vertical direction on the 2D plane.</p>
                <p>This transformation is a shear mapping (<a href="https://en.wikipedia.org/wiki/Shear_mapping">transvection</a>) 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.</p>
                <p> &mdash; <em>More Info : <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/skewY" target="_blank">https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/skewY</a></em></p>
            </details>

            <hr />
        </section>

        <p><a href="#app">Close</a></p>
    </article>

    <footer>
        <dl>
            <dt v-bind:class="{ 'visible' : cssOutput }" @click="toggleCSSOutput">CSS Output</dt>
            <dd v-bind:class="{ 'visible' : cssOutput }">
                <pre v-if="hasStyle"><code>{{ styleObject | stringOutput }}</code></pre>
                <pre v-else><code>element {
    /* No styling applied yet */
}</code></pre>
            </dd>
        </dl>
        <p>
            A project created by <strong>Jorge Moreno <a href="https://twitter.com/alterebro" title="Jorge Moreno, @alterebro. UI Developer" target="_blank">@alterebro</a></strong>
            <br /><a href="https://github.com/alterebro/css-transform" title="alterebro/css-transform repository" target="_blank">Source Code on GitHub</a> &mdash; &copy; 2019 <strong><a href="https://moro.es" title="Jorge Moreno, Moro. Front End Web Developer + UI Designer" target="_blank">www.moro.es</a></strong>
        </p>
    </footer>
</div>

              
            
!

CSS

              
                // Media Queries
@mobile-breakpoint  : 660px;
@desktop-breakpoint : 960px;

@mobile 	: ~"all and (max-width: @{mobile-breakpoint})"; 	// default
@non-mobile : ~"all and (min-width: @{mobile-breakpoint})"; 	// matching both @tablet and @desktop
@tablet 	: ~"all and (min-width: @{mobile-breakpoint}) and (max-width: @{desktop-breakpoint})";
@desktop 	: ~"all and (min-width: @{desktop-breakpoint})";
@portrait   : ~"all and (orientation: portrait)";
@landscape  : ~"all and (orientation: landscape)";

// Fonts
@import url('https://fonts.googleapis.com/css?family=Inconsolata:400,700');
@sans : -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Droid Sans", "Helvetica Neue", Arial, sans-serif;
@mono : "Andale Mono", "Monaco", "Lucida Console", "Menlo", "Consolas", "Roboto Mono", "Liberation Mono", monospace;
@font-sans : "Inconsolata", @mono;
@font-mono : @font-sans;

// Colurs
@color-bg           : #1a1718;
@color-bg-light     : lighten(@color-bg, 10%);
@color-bg-dark      : #000;
@color-fg           : #e0e1e4;
@color-fg-light     : #fff;
@color-fg-dark      : darken(@color-fg, 25%);
@color-alpha        : #25a8bf; // #05889f;
@color-alpha-light  : lighten(spin(@color-alpha, -20), 5%);
@color-alpha-dark   : darken(spin(@color-alpha, 10), 5%);
@color-beta         : #d06815; // #c05805;
@color-beta-light   : lighten(spin(@color-beta, 15), 5%);
@color-beta-dark    : darken(spin(@color-beta, -10), 5%);


// --------------------------------------------
// Pseudo-Reset
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: @color-alpha-light;
	color: @color-fg-light;
	text-shadow: none;
}
::selection {
    background-color: @color-alpha-light;
	color: @color-fg-light;
	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: @font-sans;
    font-size: 1.6em;
    line-height: 1.6;
    background: @color-bg;
    color: @color-fg;
}
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: @color-alpha;
    text-decoration: none;
    background-color: transparent;

    transition: color .25s ease-in-out;
}
a:hover { color: @color-beta-light; }
a:active, a:hover { outline: 0; }

pre, code, kbd, samp { font-family: @font-mono; }
pre {
	white-space: pre;
	white-space: pre-wrap;
	word-wrap: break-word;
	overflow: auto;

	> code {
		white-space: pre;
        display: block;
	}
}

// -----------------------------------------
// Input range styling : input[type="range"]
@range-height : 12px;
@range-track-bg : @color-bg-light;
@range-track-active-bg : @color-bg-light;
@range-handler-bg : @color-alpha;
@range-handler-active-bg : @color-beta-light;

.appears-like(@value) {
    -webkit-appearance: @value;
    -moz-appearance: @value;
    appearance: @value;
}
.appears-clean() {
    border: none;
    border-radius: 2px;
    box-shadow: none;
}
.range-input-reset() {
    .appears-like(none);
    .appears-clean()
}
.range-track() {
    height: @range-height;
    width: 100%;
    background: @range-track-bg;
    cursor: pointer;
    .range-input-reset();
    // transition: background .35s ease-in-out;
}
.range-track-active() { background: @range-track-active-bg; }
.range-handler() {
    height: @range-height;
    width: @range-height;
    background: @range-handler-bg;
    cursor: pointer;
    .range-input-reset();
    transition: background .35s ease-in-out;
}
.range-handler-active() { background: @range-handler-active-bg; }

input[type="range"] {

    .range-input-reset();
    height: @range-height;
    background: @range-track-bg;

    // Slider / Track
    &::-webkit-slider-runnable-track { .range-track() }
    &::-moz-range-track { .range-track() }
    &::-ms-track { .range-track() }
    &::-ms-fill-lower,
    &::-ms-fill-upper {
        background: @range-track-bg;
        .appears-clean();
    }

    // Handler
    &::-webkit-slider-thumb { .range-handler() }
    &::-moz-range-thumb { .range-handler() }
    &::-ms-thumb { .range-handler() }

    &:focus { outline: none; }
    &:hover {

        &::-webkit-slider-runnable-track { .range-track-active() }
        &::-moz-range-track { .range-track-active() }
        &::-ms-fill-lower { .range-track-active() }
        &::-ms-fill-upper { .range-track-active() }

        &::-webkit-slider-thumb { .range-handler-active() }
        &::-moz-range-thumb { .range-handler-active() }
        &::-ms-thumb { .range-handler-active() }
    }

    // Normalizing...
    &::-moz-focus-outer { border: 0; }
}

// -----------------------------------------
// Input Button : button, input[type="button"], input[type="submit"] ...
button {
    display: inline-block;
    padding: 0 10px;
    background-color: @color-alpha;
    border: none;
    border-radius: 2px;
    color: fade(@color-fg-light, 75%);
    cursor: pointer;
    // text-shadow: 0 -1px 0 rgba(0, 0, 0, .1);

    &[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;
    }
    &.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"); }
    &.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"); }

    &.btn-on, &.btn-off {
        background-size: 12px auto;
        background-position: right 8px center;
    }
    &.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"); }
    &.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"); }

    &:hover {
        background-color: @color-beta;
        color: fade(@color-fg-light, 99%);
    }
    &:focus { outline: none; }
}

// -----------------------------------------
// Input Checkbox : input[type="checkbox"] / (Within label with <strong> sibling)
label.checkboxed {
    position: relative;
    padding-left: 30px;
    cursor: pointer;

    input[type="checkbox"] { display: none; }
    input[type="checkbox"] + strong:before {
        content: '';
        display: block;
        width: 12px;
        height: 12px;
        background: transparent;
        border: solid @color-fg-dark 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;
    }
    input[type="checkbox"]:checked + strong:before {
        background: @color-alpha-light;
        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, fade(@color-alpha-dark, 50%), transparent),
        radial-gradient(farthest-corner at 10% 90%, fade(@color-alpha-light, 20%), transparent 80%);
    background-size: 90vw 90vw, 100% 100%;
    background-position: center center;

    &:after {
        content: '';
        display: block;
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 4px;
        background-image: linear-gradient( 90deg,
            @color-alpha-dark,
            @color-alpha,
            @color-alpha-light,
            @color-beta-light,
            @color-beta,
            @color-beta-dark
        );
        box-shadow: 0 1px 0 0 rgba(0, 0, 0, .35);
    }
}

section#do {
    z-index: 3;
    position: fixed;
    top: 0;
    right: 0;

    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, .2);

        &:hover { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .4) }

        em {
            display: block;
            text-indent: -1000rem;
            position: absolute;
            transform: translateY(-50%);
            top: 50%;
            left: 12px;
            width: 16px;
        }
    }

    a#open { // ≡

        right: 2rem;
        opacity: 1;

        em {

            border-top: solid #fff 2px;
            border-bottom: solid #fff 2px;
            height: 14px; // 16px;

            &:after {
                content: '';
                display: block;
                width: 100%;
                height: 2px;
                background: #fff;
                position: absolute;
                top: 50%;
                margin-top: -1px;
            }
        }
    }

    a#close { // ×

        right: -6rem;
        opacity: 0;

        em {

            height: 16px;

            &:before, &:after {
                content: '';
                display: block;
                width: (sqrt(2) * 16px) - 1px;
                height: 2px;
                background: #fff;
                position: absolute;
            }
            &:before {
                top: 0;
                left: 0;
                transform: rotate(45deg);
                transform-origin: 1px 1px;
            }

            &:after {
                bottom: 0;
                left: 0;
                transform: rotate(-45deg);
                transform-origin: 1px 1px;
            }
        }
    }
}

// -----------------------

@aside-bg : rgba(0, 0, 0, .65);
@aside-width : 42rem;

header {

    z-index: 2;
    position: fixed;
    top: 0;
    right: -(@aside-width);

    height: 80px;
    width: 100%;
    max-width: @aside-width;
    background: @aside-bg;
    padding: 2rem;
    box-shadow:
        inset 0 4px 0 @color-alpha,
        inset 0 5px 0 #000,
        0 2px 0 0 rgba(0, 0, 0, .5);

    border-bottom: solid fade(@color-alpha, 50%) 1px;
    overflow: hidden;

    transition: right .25s ease-in-out;

    h1, p {
        width: 100%;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
        padding: 0 50px 0 0;
    }

    h1 {
        font-size: 2.2rem;
        font-weight: 700;
        color: @color-fg-light;
        margin: 0 0 2px;
        line-height: 1;
        height: 22px;
    }
    p {
        line-height: 1.4;
        height: 18px;
    }
}

aside {
    z-index: 1;
    position: fixed;
    top: 80px;
    right: -(@aside-width);

    height: ~"calc(100% - 80px)";
    width: 100%;
    max-width: @aside-width;
    background: @aside-bg;
    overflow: auto;

    transition: right .25s ease-in-out;

    form {
        padding: 2rem;

        fieldset {
            border: none;

            > legend { font-weight: 700 }
            > dl {
                dt:first-child { margin-top: 1rem; }
                dt {
                    margin: 1.5rem 0 .5rem 0;
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    line-height: 30px;
                    background: @color-bg-dark;
                    border-radius: 3px;

                    > label { flex: 1 1 auto; }
                    > 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;
                    }
                }
                dd { padding: .2rem 0; }
                dd:not(.buttons) {
                    display: flex;
                    align-items: center;
                    justify-content: space-between;

                    label {
                        display: inline-block;
                        padding-left: 5px;
                        min-width: 14.5rem;
                        flex: 0 0 14.5rem;
                    }
                    input {
                        display: block;
                        width: 100%;
                        flex: 1 1 auto;
                    }
                    code {
                        display: inline-block;
                        text-align: right;
                        padding: 0 5px 0 0;
                        font-size: .9em;
                        flex: 0 0 5rem;
                        color: @color-fg-dark;
                    }
                }
                dd.buttons {
                    text-align: right;
                    padding: .5rem 5rem 0 0;
                }
            }

            > p {
                margin-top: 2rem;
                overflow: auto;

                button {
                    float: left;
                    margin: 0 .5rem .5rem 0;
                }
            }
        }

        fieldset:last-child {
            margin: 3rem 0 0 0;
            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;

    #box {
        display: inline-block;
        height: 80vh;
        width: 80vh;
        background: fade(@color-bg-dark, 50%);
        box-shadow: 0 0 0 1px fade(@color-alpha, 50%);
        position: relative;

        @media @landscape {
            height: 80vh;
            width: 80vh;
        }
        @media @portrait {
            height: 80vw;
            width: 80vw;
        }
    }

    #alpha {
        position: absolute;
        border: solid white 10px;
        width: ~"calc(100% - 20px)";
        height: ~"calc(100% - 20px)";
        margin: 10px;
        transition: all .5s ease-in-out;

        &:before, &:after {
            content: '';
            display: block;
            position: absolute;
        }
        &:before {
            top: 50%;
            left: -15%;
            height: 0;
            width: 130%;
            border-top: dotted fade(@color-fg-light, 50%) 1px;
        }
        &:after {
            top: -15%;
            left: 50%;
            height: 130%;
            width: 0;
            border-left: dotted fade(@color-fg-light, 50%) 1px;
        }

        transform-style: preserve-3d;
        -webkit-transform-style: preserve-3d;

        .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 fade(@color-alpha, 50%);
            background-color: rgba(0, 0, 0, .1);
            opacity: 0;
            transition: all .35s ease-in-out;

            &.active { opacity: 1 }

            strong {
                opacity: 0;
                font-size: 24px;
                font-weight: normal;
                color: @color-fg-light;
                text-transform: uppercase;
                letter-spacing: 2px;

                transition: opacity .35s ease-in-out;
            }

            &:hover {
                box-shadow: inset 0 0 0 10px @color-beta;
                background-color: rgba(0, 0, 0, .5);
                strong { opacity: 1; }
            }
        }
        #alpha-front { transform: translateZ(100px) }
        #alpha-back { transform: translateZ(-100px) }
    }
}


#app.with-sidebar {

    section#do {

        a#open { // ≡
            right: @aside-width + 2rem;
            opacity: 0;
        }

        a#close { // ×
            right: 2rem;
            opacity: 1;
        }
    }

    header { right: 0 }
    aside { right: 0 }
    main {
        @media @desktop {
            width: ~"calc(100% - @{aside-width})";
        }
    }
}


// -----------------
// Info Modal Window

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;

    &.visible {
        opacity: 1;
        background: rgba(0, 0, 0, .75);
    }
    &.gone { display: none; }

    > section {
        order: 2;
        display: none;
        width: 90%;
        max-width: 72rem;
        padding: 4rem;
        background: @color-bg-dark;
        border: solid fade(@color-alpha, 50%) 1px;

        h2 {
            font-size: 2rem;
            line-height: 1;
            margin: 0;
            font-weight: 400;
        }
        h3 {
            font-size: 1.6rem;
            color: @color-fg-dark;
            margin: 0 0 1rem;
        }

        p { margin: 0 0 1rem; }

        ul {
            margin: 0 0 1rem 2rem;

            li {
                list-style: square;
                margin: 0 0 .5rem;
                &:last-child { margin: 0 }
            }
        }

        details {
            padding: 1rem 0 0;
            summary {
                cursor: pointer;
                h3 {
                    display: inline-block;
                    margin: 0;
                }
                &[open] { margin: 0 0 1rem; }
                &:focus { outline: none; }
            }
        }

        pre {
            border: dotted @color-fg-dark 1px;
            border-radius: 3px;
            margin: 1rem 0 2rem;

            > code {
                font-size: .9em;
                color: @color-fg-dark;
                padding: 1rem 2rem;
            }
        }
    }

    > p {
        order: 1;
        width: 90%;
        max-width: 72rem;
        text-align: right;
        position: relative;

        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: @aside-bg;
    border-top-right-radius: 3px;

    p {
        line-height: 1.5;
        padding: 0 5px 0 0;
    }

    dl {
        border-bottom: solid fade(@color-alpha, 50%) 1px;
        margin: 0 0 .5rem;
        padding: 0;

        dt {
            margin: 0;
            padding: 0 0 .5rem 16px;
            cursor: pointer;
            position: relative;
            font-weight: bold;
            color: @color-alpha;
            &:hover { color: @color-beta-light; }

            transition: color .25s ease-in-out;

            &:before {
                content: '';
                display: block;
                position: absolute;
                top: 6px;
                left: 4px;
                width: 6px;
                height: 6px;

                border-top: solid 6px @color-fg;
                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);
            }

            &.visible:before { transform: rotate(0deg); }
        }
        dd {
            max-height: 0;
            overflow: hidden;
            transition: max-height .35s ease-in-out;

            pre {
                border: dotted @color-fg-dark 1px;
                margin: 0 0 1rem;
                padding: 0;

                > code {
                    margin: 0;
                    padding: 1rem;
                    color: @color-fg-light;
                    cursor: text;
                }
            }
            &.visible { max-height: 320px; }
        }
    }
}

              
            
!

JS

              
                
const randomInt = function(min, max) {
	// Returns a random integer between @min and @max (inclusive)
	let _max = parseInt(max);
	let _min = parseInt(min);
	return Math.floor(Math.random() * ((_max - _min) + 1)) + _min;
}

const Data = {

    rotate2Dactive : false,
    rotate2D : 10,

    rotate3Dactive : false,
	rotateX : 10,
	rotateY : 10,
	rotateZ : 0,

    perspectiveActive : false,
	perspective : 700,

    transformOriginActive : false,
	transformOriginX : 50,
	transformOriginY : 50,
	transformOriginZ : -70,

    scaleActive : false,
	scale : 1,

	translateActive : false,
	translateX : -10,
	translateY : -20,

	skewActive : false,
	skewX : 10,
	skewY : 10,

    modal : {
        visible : false,
        current : null
    },

	sidebar : false,
	cssOutput : false
}

const App = new Vue({

    el : '#app',
    data : Data,

    mounted() {

        let infoSections = Array.from( document.querySelectorAll('#app > article section') );
            infoSections.forEach( (el) => {
                el.addEventListener('click', (e) => e.stopPropagation() );
            });

        let infoTriggers = Array.from( document.querySelectorAll('#app > aside dl dt a') );
            infoTriggers.forEach( (el) => {

                el.addEventListener('click', (e) => {
                    e.preventDefault();

                        let _current = el.href.split('#')[1];
                        this.modal.current = _current;
                        infoSections.forEach( (el) => el.style.display = 'none' );
                        document.querySelector( `#app > article section#${_current}`).style.display = 'block';

                    this.modalWindowShow();
                });
            });

        // Modal window close handlers
        let infoCloser = document.querySelector('#app > article > p a');
            infoCloser.addEventListener('click', (e) => {
                e.preventDefault();
                this.modalWindowHide();
            });
            document.querySelector('#app > article').addEventListener('click', () => this.modalWindowHide() );

		// Init (close)
		this.modalWindowHide()

		// Some keyboard action
		document.addEventListener('keyup', e => {

			if ( e.keyCode === 27 ) { this.modalWindowHide() } 		// 'Esc' to close modal
			if ( e.keyCode === 9 ) { this.sidebar = !this.sidebar } // 'Tab' to toggle Sidebar
			if ( e.keyCode === 32 ) { this.toggleCSSOutput() } 		// 'Space' to toggle CSS Output

			if ( e.keyCode === 49 ) { this.randomAll() } 			// Num key 1
			if ( e.keyCode === 50 ) { this.resetAll() }				// Num key 2
			if ( e.keyCode === 51 ) { this.activateAll(true) }		// Num key 3
			if ( e.keyCode === 52 ) { this.activateAll(false) }		// Num key 4
		})

        // Accordion
		// TODO : Close when only one is open
        let detailsBlocks = Array.from( document.querySelectorAll('#app > article > section details summary') );
            detailsBlocks.forEach( (el) => {

                el.addEventListener('click', (e) => {

                    e.preventDefault();
                    let _detailsChildren = Array.from( el.parentNode.parentNode.querySelectorAll('details') );
                        _detailsChildren.forEach( (_el) => _el.removeAttribute('open') );
                    el.parentNode.setAttribute('open', '');
                });
            });


		// INTRO
		// Chain of Actions
		let actionsChain =
			chainTimeout( () => this.cssOutput = true, 250 )
			.chainTimeout( () => {
				this.transformOriginActive = true;
				this.rotate2Dactive = true;
			}, 250 )
			.chainTimeout( () => this.rotate3Dactive = true, 500 )
			.chainTimeout( () => this.rotateZ = 10, 500 )
			.chainTimeout( () => this.perspectiveActive = true, 500 )
			.chainTimeout( () => {
				this.perspective = 1500;
				this.rotateZ = -45;
			}, 500 )
			.chainTimeout( () => {
				this.scaleActive = true;
				this.scale = 0.8;
			}, 500 )
			.chainTimeout( () => this.translateActive = true, 500 )
			.chainTimeout( () => this.skewActive = true, 500 )
			.chainTimeout( () => {
				this.rotateY = 40;
				this.rotateZ = 0;
				this.perspective = 800;
				this.scale = 0.9;
				this.translateX = -50;
				this.translateY = 0;
				this.skewX = 0;
				this.skewY = 0;
			}, 500 )
			.chainTimeout( () => this.sidebar = true , 500 )
			.chainTimeout( () => this.cssOutput = false , 250 )
			.chainTimeout( () => this.resetAll() , 250 )
			.chainTimeout( () => this.sidebar = false , 1000 )

		// -----
		// Info dialog on the console
		let keyCommands = [
			' • Esc : Closes info modal window when opened.',
			' • Tab : Open / closes the sidebar.',
			' • Space : Open / closes the CSS Output footer panel.',
			' • Num. #1 : Random All transform functions.',
			' • Num. #2 : Reset All transform functions.',
			' • Num. #3 : Activate All transform functions.',
			' • Num. #4 : Deactivate All transform functions.',
		];

		console.log(
			'\n' +
			'%ccss-transform' +
			'%c\nKeyboard commands:' +
			'%c\n' + keyCommands.join("\n") +
			'%c\n@alterebro - https://twitter.com/alterebro' +
			'\n',

			'color: #fff; background-color: #444; padding: 5px 10px; margin: 10px 0 5px; border-radius: 3px;',
			'font-weight: bold; margin: 5px; display: block;',
			'line-height: 1.5; font-family: monospace; color: #217eaa',
			'margin: 5px 10px; display: block; font-size: 90%; color: #777'
		);
    },

	computed : {

		styleObject() {

			const _styles = {
				'transform' : [],
				'transform-origin' : null
			};

			let _trFunctions = [];

				// Rotate 2D
				if ( this.rotate2D != 0 && this.rotate2D != 360 && this.rotate2Dactive ) { _trFunctions.push( 'rotate('+this.rotate2D + 'deg)' ) }

				// Rotate 3D
				if ( this.rotate3Dactive ) {
					if ( this.rotateX && this.rotateX != 0 ) { _trFunctions.push( 'rotateX('+this.rotateX + 'deg)' ) }
					if ( this.rotateY && this.rotateY != 0 ) { _trFunctions.push( 'rotateY('+this.rotateY + 'deg)' ) }
					if ( this.rotateZ && this.rotateZ != 0 ) { _trFunctions.push( 'rotateZ('+this.rotateZ + 'deg)' ) }
				}

				// Perspective
				if ( this.perspectiveActive ) { _trFunctions.push( 'perspective('+this.perspective + 'px)' ) }

				// Scale
				if ( this.scaleActive && this.scale != 1 ) { _trFunctions.push('scale('+this.scale+')') }

				// Translate
				if ( this.translateActive && (this.translateX !=0 || this.translateY !=0) ) { _trFunctions.push('translate('+this.translateX+'px,'+this.translateY+'px)') }

				// Skew
				if ( this.skewActive && (this.skewX !=0 || this.skewY !=0) ) { _trFunctions.push('skew('+this.skewX+'deg,'+this.skewY+'deg)') }

			_styles['transform'] = _trFunctions;


			if ( this.transformOriginActive ) {

				let _x = { 0 : 'left', 50 : 'center', 100 : 'right' };
				let _y = { 0 : 'top', 50 : 'center', 100 : 'bottom' };

				let origin_x = ( this.transformOriginX == 0 || this.transformOriginX == 50 || this.transformOriginX == 100 )
					? _x[this.transformOriginX]
					: this.transformOriginX+'%';

				let origin_y = ( this.transformOriginY == 0 || this.transformOriginY == 50 || this.transformOriginY == 100 )
					? _y[this.transformOriginY]
					: this.transformOriginY+'%';

				let output = origin_x + ' ' + origin_y;
				 	output = ( this.transformOriginZ && this.transformOriginZ != 0 ) ? output + ' ' + this.transformOriginZ + 'px' : output;

				_styles['transform-origin'] = output;
			}

			return _styles;
		},

		styleClass() {
			return {
				'transform' : this.styleObject.transform.join(' '),
				'transformOrigin' : (this.styleObject['transform-origin']) ? this.styleObject['transform-origin'] : ''
			}
		},

		hasStyle() {
			return (this.styleObject.transform.length > 0) || (this.styleObject['transform-origin'] != null);
		},

		isActivated() {
			return !(
				this.transformOriginActive == false &&
				this.rotate2Dactive == false &&
				this.rotate3Dactive == false &&
				this.perspectiveActive == false &&
				this.scaleActive == false &&
				this.translateActive == false &&
				this.skewActive == false
			);
		},

	},

	filters : {

		stringOutput(obj) {

			let _output = [];

				if ( !!obj['transform'].length ) { _output.push( `transform: ${obj['transform'].join('\n\t\t')};` ) }
				if ( !!obj['transform-origin'] ) { _output.push( `transform-origin: ${obj['transform-origin']};` ) }

			return (_output.length) ? `element {\n\t${_output.join('\n\t')}\n}` : '';
		}

	},

    methods : {

		// ------------------
		// - Modal Info Window
        modalWindowShow() {
			let _modal = document.querySelector('#app > article');
				_modal.classList.remove('gone');
				chainTimeout( () => _modal.classList.add('visible'), 10 );
		},
        modalWindowHide() {
			let _modal = document.querySelector('#app > article');
				_modal.classList.remove('visible');
				chainTimeout( () => _modal.classList.add('gone'), 350 );
		},

		// ------------------
		// - Sidebar
		openSidebar() { this.sidebar = true },
		closeSidebar() { this.sidebar = false },

		// ------------------
		// - CSS Output
		toggleCSSOutput() { this.cssOutput = !this.cssOutput },

		// ------------------
		// - Transform Functions

		// Rotate 2D
		randomRotate2D() { this.rotate2D = randomInt(0, 359) },
        resetRotate2D() { this.rotate2D = 0 },

		// Rotate 3D
		randomRotate3D() {
			this.rotateX = randomInt(0, 359);
			this.rotateY = randomInt(0, 359);
			this.rotateZ = randomInt(0, 359);
		},
		resetRotate3D() { this.rotateX = this.rotateY = this.rotateZ = 0; },

		// Perspective
		randomPerspective() { this.perspective = (randomInt(3, 23) * 100) },
		resetPerspective() { this.perspective = 700 },

		// Transform Origin
		randomTransformOrigin() {
			this.transformOriginX = randomInt(0, 100);
			this.transformOriginY = randomInt(0, 100);
			this.transformOriginZ = randomInt(-250, 250);
		},
		resetTransformOrigin() {
			this.transformOriginX = this.transformOriginY = 50;
			this.transformOriginZ = 0;
		},

		// Scale
		randomScale() { this.scale = (randomInt(5, 20) / 10) },
		resetScale() { this.scale = 1; },

		// Translate
		randomTranslate() {
			this.translateX = (randomInt(-10, 10) * 10);
			this.translateY = (randomInt(-10, 10) * 10);
		},
		resetTranslate() { this.translateX = this.translateY = 0 },

		// Skew
		randomSkew() {
			this.skewX = randomInt(0, 180);
			this.skewY = randomInt(0, 180);
		},
		resetSkew() { this.skewX = this.skewY = 0 },

		// ------------------
		// - Multiple Transform Action
		randomAll : function() {
			this.randomTransformOrigin();
			this.randomRotate2D();
			this.randomRotate3D();
			this.randomPerspective();
			this.randomScale();
			this.randomTranslate();
			this.randomSkew();
		},
		resetAll : function() {
			this.resetTransformOrigin();
			this.resetRotate2D();
			this.resetRotate3D();
			this.resetPerspective();
			this.resetScale();
			this.resetTranslate();
			this.resetSkew();
		},
		activateAll : function(seriously) { this.transformOriginActive = this.rotate2Dactive = this.rotate3Dactive = this.perspectiveActive = this.scaleActive = this.translateActive = this.skewActive = seriously }

    }

});

              
            
!
999px

Console