aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/css/css_box_model
diff options
context:
space:
mode:
authorPeter Bengtsson <mail@peterbe.com>2020-12-08 14:40:17 -0500
committerPeter Bengtsson <mail@peterbe.com>2020-12-08 14:40:17 -0500
commit33058f2b292b3a581333bdfb21b8f671898c5060 (patch)
tree51c3e392513ec574331b2d3f85c394445ea803c6 /files/zh-cn/web/css/css_box_model
parent8b66d724f7caf0157093fb09cfec8fbd0c6ad50a (diff)
downloadtranslated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.gz
translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.bz2
translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.zip
initial commit
Diffstat (limited to 'files/zh-cn/web/css/css_box_model')
-rw-r--r--files/zh-cn/web/css/css_box_model/box-shadow_generator/index.html2880
-rw-r--r--files/zh-cn/web/css/css_box_model/index.html112
-rw-r--r--files/zh-cn/web/css/css_box_model/introduction_to_the_css_box_model/index.html82
-rw-r--r--files/zh-cn/web/css/css_box_model/mastering_margin_collapsing/index.html151
4 files changed, 3225 insertions, 0 deletions
diff --git a/files/zh-cn/web/css/css_box_model/box-shadow_generator/index.html b/files/zh-cn/web/css/css_box_model/box-shadow_generator/index.html
new file mode 100644
index 0000000000..3fb264bc40
--- /dev/null
+++ b/files/zh-cn/web/css/css_box_model/box-shadow_generator/index.html
@@ -0,0 +1,2880 @@
+---
+title: Box-shadow generator
+slug: Web/CSS/CSS_Box_Model/Box-shadow_generator
+translation_of: Web/CSS/CSS_Background_and_Borders/Box-shadow_generator
+---
+<p>这个可视化工具可以帮助你生成一个元素的CSS{{cssxref("box-shadow")}}相关代码,添加box shadow效果到你的CSS对象上。</p>
+
+<div style="display: none;">
+<h2 id="box-shadow_generator" name="box-shadow_generator">box-shadow generator</h2>
+
+<h3 id="HTML_Content">HTML Content</h3>
+
+<pre class="brush: html">&lt;div id="container"&gt;
+    &lt;div class="group section"&gt;
+        &lt;div id="layer_manager"&gt;
+            &lt;div class="group section"&gt;
+                &lt;div class="button" data-type="add"&gt; &lt;/div&gt;
+                &lt;div class="button" data-type="move-up"&gt; &lt;/div&gt;
+                &lt;div class="button" data-type="move-down"&gt; &lt;/div&gt;
+            &lt;/div&gt;
+            &lt;div id="stack_container"&gt;&lt;/div&gt;
+        &lt;/div&gt;
+
+        &lt;div id="preview_zone"&gt;
+            &lt;div id="layer_menu" class="col span_12"&gt;
+                &lt;div class="button" id="element" data-type="subject" data-title="element"&gt; element &lt;/div&gt;
+                &lt;div class="button" id="before" data-type="subject" data-title=":before"&gt;
+                    :before
+                    &lt;span class="delete" data-type="disable"&gt;&lt;/span&gt;
+                &lt;/div&gt;
+                &lt;div class="button" id="after" data-type="subject" data-title=":after"&gt;
+                    :after
+                    &lt;span class="delete" data-type="disable"&gt;&lt;/span&gt;
+                &lt;/div&gt;
+                &lt;div class="ui-checkbox" data-topic='before' data-label=":before"&gt;&lt;/div&gt;
+                &lt;div class="ui-checkbox" data-topic='after' data-label=":after"&gt;&lt;/div&gt;
+            &lt;/div&gt;
+
+            &lt;div id="preview"&gt;
+                &lt;div id="obj-element"&gt;
+                    &lt;div class="content"&gt; &lt;/div&gt;
+                    &lt;div id="obj-before"&gt; &lt;/div&gt;
+                    &lt;div id="obj-after"&gt; &lt;/div&gt;
+                &lt;/div&gt;
+            &lt;/div&gt;
+        &lt;/div&gt;
+    &lt;/div&gt;
+
+    &lt;div id="controls" class="group section"&gt;
+        &lt;div class="wrap-left"&gt;
+            &lt;div class="colorpicker category"&gt;
+                &lt;div class="title"&gt; &lt;/div&gt;
+                &lt;div id="colorpicker" class="group"&gt;
+                    &lt;div id="gradient" class="gradient"&gt;
+                        &lt;div id="gradient_picker"&gt; &lt;/div&gt;
+                    &lt;/div&gt;
+                    &lt;div id="hue" data-topic="hue" class="hue"&gt;
+                        &lt;div id="hue_selector"&gt; &lt;/div&gt;
+                    &lt;/div&gt;
+                    &lt;div class="info"&gt;
+                        &lt;div class="input" data-topic="hue" data-title='H:' data-action="HSV"&gt;&lt;/div&gt;
+                        &lt;div class="input" data-topic="saturation" data-title='S:' data-action="HSV"&gt;&lt;/div&gt;
+                        &lt;div class="input" data-topic="value" data-title='V:' data-action="HSV"&gt;&lt;/div&gt;
+                    &lt;/div&gt;
+                    &lt;div class="alpha"&gt;
+                        &lt;div id="alpha" data-topic="alpha"&gt;
+                            &lt;div id="alpha_selector"&gt; &lt;/div&gt;
+                        &lt;/div&gt;
+                    &lt;/div&gt;
+                    &lt;div class="info"&gt;
+                        &lt;div class="input" data-topic="r" data-title='R:' data-action="RGB"&gt;&lt;/div&gt;
+                        &lt;div class="input" data-topic="g" data-title='G:' data-action="RGB"&gt;&lt;/div&gt;
+                        &lt;div class="input" data-topic="b" data-title='B:' data-action="RGB"&gt;&lt;/div&gt;
+                    &lt;/div&gt;
+                    &lt;div class="preview block"&gt;
+                        &lt;div id="output_color"&gt; &lt;/div&gt;
+                    &lt;/div&gt;
+                    &lt;div class="block info"&gt;
+                        &lt;div class="input" data-topic="a" data-title='alpha:' data-action="alpha"&gt;&lt;/div&gt;
+                        &lt;div class="input" data-topic="hexa" data-title='' data-action="hexa"&gt;&lt;/div&gt;
+                    &lt;/div&gt;
+                &lt;/div&gt;
+            &lt;/div&gt;
+        &lt;/div&gt;
+
+        &lt;div class="wrap-right"&gt;
+
+            &lt;div id="shadow_properties" class="category"&gt;
+                &lt;div class="title"&gt; Shadow properties &lt;/div&gt;
+                &lt;div class="group"&gt;
+                    &lt;div class="group property"&gt;
+                        &lt;div class="ui-slider-name"&gt; inset &lt;/div&gt;
+                        &lt;div class="ui-checkbox" data-topic='inset'&gt;&lt;/div&gt;
+                    &lt;/div&gt;
+                    &lt;div class="slidergroup"&gt;
+                        &lt;div class="ui-slider-name"&gt; Position x &lt;/div&gt;
+                        &lt;div class="ui-slider-btn-set" data-topic="posX" data-type="sub"&gt;&lt;/div&gt;
+                        &lt;div class="ui-slider" data-topic="posX"
+                            data-min="-500" data-max="500" data-step="1"&gt; &lt;/div&gt;
+                        &lt;div class="ui-slider-btn-set" data-topic="posX" data-type="add"&gt;&lt;/div&gt;
+                        &lt;div class="ui-slider-input" data-topic="posX" data-unit="px"&gt;&lt;/div&gt;
+                    &lt;/div&gt;
+                    &lt;div class="slidergroup"&gt;
+                        &lt;div class="ui-slider-name"&gt; Position y &lt;/div&gt;
+                        &lt;div class="ui-slider-btn-set" data-topic="posY" data-type="sub"&gt;&lt;/div&gt;
+                        &lt;div class="ui-slider" data-topic="posY"
+                            data-min="-500" data-max="500" data-step="1"&gt; &lt;/div&gt;
+                        &lt;div class="ui-slider-btn-set" data-topic="posY" data-type="add"&gt;&lt;/div&gt;
+                        &lt;div class="ui-slider-input" data-topic="posY" data-unit="px"&gt;&lt;/div&gt;
+                    &lt;/div&gt;
+                    &lt;div class="slidergroup"&gt;
+                        &lt;div class="ui-slider-name"&gt; Blur &lt;/div&gt;
+                        &lt;div class="ui-slider-btn-set" data-topic="blur" data-type="sub"&gt;&lt;/div&gt;
+                        &lt;div class="ui-slider" data-topic="blur"
+                            data-min="0" data-max="200" data-step="1"&gt; &lt;/div&gt;
+                        &lt;div class="ui-slider-btn-set" data-topic="blur" data-type="add"&gt;&lt;/div&gt;
+                        &lt;div class="ui-slider-input" data-topic="blur" data-unit="px"&gt;&lt;/div&gt;
+                    &lt;/div&gt;
+                    &lt;div class="slidergroup"&gt;
+                        &lt;div class="ui-slider-name"&gt; Spread &lt;/div&gt;
+                        &lt;div class="ui-slider-btn-set" data-topic="spread" data-type="sub"&gt;&lt;/div&gt;
+                        &lt;div class="ui-slider" data-topic="spread"
+                            data-min="-100"    data-max="100" data-step="1" data-value="50"&gt;
+                        &lt;/div&gt;
+                        &lt;div class="ui-slider-btn-set" data-topic="spread" data-type="add"&gt;&lt;/div&gt;
+                        &lt;div class="ui-slider-input" data-topic="spread" data-unit="px"&gt;&lt;/div&gt;
+                    &lt;/div&gt;
+                &lt;/div&gt;
+            &lt;/div&gt;
+
+            &lt;div id="element_properties" class="category"&gt;
+                &lt;div class="title"&gt; Class element properties &lt;/div&gt;
+                &lt;div class="group"&gt;
+                    &lt;div class="group property"&gt;
+                        &lt;div class="ui-slider-name"&gt; border &lt;/div&gt;
+                        &lt;div class="ui-checkbox" data-topic='border-state' data-state="true"&gt;&lt;/div&gt;
+                    &lt;/div&gt;
+                    &lt;div id="z-index" class="slidergroup"&gt;
+                        &lt;div class="ui-slider-name"&gt; z-index &lt;/div&gt;
+                        &lt;div class="ui-slider-btn-set" data-topic="z-index" data-type="sub"&gt;&lt;/div&gt;
+                        &lt;div class="ui-slider" data-topic="z-index"
+                            data-min="-10" data-max="10" data-step="1"&gt;&lt;/div&gt;
+                        &lt;div class="ui-slider-btn-set" data-topic="z-index" data-type="add"&gt;&lt;/div&gt;
+                        &lt;div class="ui-slider-input" data-topic="z-index"&gt;&lt;/div&gt;
+                    &lt;/div&gt;
+                    &lt;div class="slidergroup"&gt;
+                        &lt;div class="ui-slider-name"&gt; top &lt;/div&gt;
+                        &lt;div class="ui-slider-btn-set" data-topic="top" data-type="sub"&gt;&lt;/div&gt;
+                        &lt;div class="ui-slider" data-topic="top"
+                            data-min="-500" data-max="500" data-step="1"&gt; &lt;/div&gt;
+                        &lt;div class="ui-slider-btn-set" data-topic="top" data-type="add"&gt;&lt;/div&gt;
+                        &lt;div class="ui-slider-input" data-topic="top" data-unit="px"&gt;&lt;/div&gt;
+                    &lt;/div&gt;
+                    &lt;div class="slidergroup"&gt;
+                        &lt;div class="ui-slider-name"&gt; left &lt;/div&gt;
+                        &lt;div class="ui-slider-btn-set" data-topic="left" data-type="sub"&gt;&lt;/div&gt;
+                        &lt;div class="ui-slider" data-topic="left"
+                            data-min="-300" data-max="700" data-step="1"&gt; &lt;/div&gt;
+                        &lt;div class="ui-slider-btn-set" data-topic="left" data-type="add"&gt;&lt;/div&gt;
+                        &lt;div class="ui-slider-input" data-topic="left" data-unit="px"&gt;&lt;/div&gt;
+                    &lt;/div&gt;
+                    &lt;div id="transform_rotate" class="slidergroup"&gt;
+                        &lt;div class="ui-slider-name"&gt; Rotate &lt;/div&gt;
+                        &lt;div class="ui-slider-btn-set" data-topic="rotate" data-type="sub"&gt;&lt;/div&gt;
+                        &lt;div class="ui-slider" data-topic="rotate"
+                            data-min="-360" data-max="360" data-step="1" data-value="0"&gt;
+                        &lt;/div&gt;
+                        &lt;div class="ui-slider-btn-set" data-topic="rotate" data-type="add"&gt;&lt;/div&gt;
+                        &lt;div class="ui-slider-input" data-topic="rotate" data-unit="deg"&gt;&lt;/div&gt;
+                    &lt;/div&gt;
+                    &lt;div class="slidergroup"&gt;
+                        &lt;div class="ui-slider-name"&gt; Width &lt;/div&gt;
+                        &lt;div class="ui-slider-btn-set" data-topic="width" data-type="sub"&gt;&lt;/div&gt;
+                        &lt;div class="ui-slider" data-topic="width"
+                            data-min="0" data-max="1000" data-step="1" data-value="200"&gt;
+                        &lt;/div&gt;
+                        &lt;div class="ui-slider-btn-set" data-topic="width" data-type="add"&gt;&lt;/div&gt;
+                        &lt;div class="ui-slider-input" data-topic="width"  data-unit="px"&gt;&lt;/div&gt;
+                    &lt;/div&gt;
+                    &lt;div class="slidergroup"&gt;
+                        &lt;div class="ui-slider-name"&gt; Height &lt;/div&gt;
+                        &lt;div class="ui-slider-btn-set" data-topic="height" data-type="sub"&gt;&lt;/div&gt;
+                        &lt;div class="ui-slider" data-topic="height"
+                            data-min="0" data-max="400" data-step="1" data-value="200"&gt;
+                        &lt;/div&gt;
+                        &lt;div class="ui-slider-btn-set" data-topic="height" data-type="add"&gt;&lt;/div&gt;
+                        &lt;div class="ui-slider-input" data-topic="height" data-unit="px"&gt;&lt;/div&gt;
+                    &lt;/div&gt;
+                &lt;/div&gt;
+            &lt;/div&gt;
+
+            &lt;div id="output" class="category"&gt;
+                &lt;div id="menu" class="menu"&gt;&lt;/div&gt;
+                &lt;div class="title"&gt;    CSS Code &lt;/div&gt;
+                &lt;div class="group" style="border-top-left-radius: 0;"&gt;
+                    &lt;div class="output" data-topic="element" data-name="element"
+                        data-prop="width height background-color position=[relative] box-shadow"&gt;
+                    &lt;/div&gt;
+                    &lt;div class="output" data-topic="before" data-name="element:before"
+                        data-prop="content=[&amp;quot;&amp;quot;] position=[absolute] width height top left z-index background-color box-shadow transform -webkit-transform -ms-transform"&gt;
+                    &lt;/div&gt;
+                    &lt;div class="output" data-topic="after" data-name="element:after"
+                        data-prop="content=[&amp;quot;&amp;quot;] position=[absolute] width height top left z-index background-color box-shadow transform -webkit-transform -ms-transform"&gt;
+                    &lt;/div&gt;
+                &lt;/div&gt;
+            &lt;/div&gt;
+        &lt;/div&gt;
+    &lt;/div&gt;
+&lt;/div&gt;
+</pre>
+
+<h3 id="CSS_Content">CSS Content</h3>
+
+<pre class="brush: css">/* GRID OF TWELVE
+ * ========================================================================== */
+
+.span_12 {
+ width: 100%;
+}
+
+.span_11 {
+ width: 91.46%;
+}
+
+.span_10 {
+ width: 83%;
+}
+
+.span_9 {
+ width: 74.54%;
+}
+
+.span_8 {
+ width: 66.08%;
+}
+
+.span_7 {
+ width: 57.62%;
+}
+
+.span_6 {
+ width: 49.16%;
+}
+
+.span_5 {
+ width: 40.7%;
+}
+
+.span_4 {
+ width: 32.24%;
+}
+
+.span_3 {
+ width: 23.78%;
+}
+
+.span_2 {
+ width: 15.32%;
+}
+
+.span_1 {
+ width: 6.86%;
+}
+
+
+/* SECTIONS
+ * ========================================================================== */
+
+.section {
+ clear: both;
+ padding: 0px;
+ margin: 0px;
+}
+
+/* GROUPING
+ * ========================================================================== */
+
+
+.group:before, .group:after {
+ content: "";
+ display: table;
+}
+
+.group:after {
+ clear:both;
+}
+
+.group {
+ zoom: 1; /* For IE 6/7 (trigger hasLayout) */
+}
+
+/* GRID COLUMN SETUP
+ * ========================================================================== */
+
+.col {
+ display: block;
+ float:left;
+ margin: 1% 0 1% 1.6%;
+}
+
+.col:first-child {
+ margin-left: 0;
+} /* all browsers except IE6 and lower */
+
+/*
+ * UI Slider
+ */
+
+.slidergroup {
+ height: 20px;
+ margin: 10px 0;
+ font-family: "Segoe UI", Arial, Helvetica, sans-serif;
+ -moz-user-select: none;
+ user-select: none;
+}
+
+.slidergroup * {
+ float: left;
+ height: 100%;
+ line-height: 100%;
+}
+
+/* Slider */
+
+.ui-slider {
+ height: 10px;
+ width: 200px;
+ margin: 4px 10px;
+ display: block;
+ border: 1px solid #999;
+ border-radius: 3px;
+ background: #EEE;
+}
+
+.ui-slider:hover {
+ cursor: pointer;
+}
+
+.ui-slider-name {
+ width: 90px;
+ padding: 0 10px 0 0;
+ text-align: right;
+ text-transform: lowercase;
+}
+
+.ui-slider-pointer {
+ width: 13px;
+ height: 13px;
+ background-color: #EEE;
+ border: 1px solid #2C9FC9;
+ border-radius: 3px;
+ position: relative;
+ top: -3px;
+ left: 0%;
+}
+
+.ui-slider-btn-set {
+ width: 25px;
+ background-color: #2C9FC9;
+ border-radius: 3px;
+ color: #FFF;
+ font-weight: bold;
+ text-align: center;
+}
+
+.ui-slider-btn-set:hover {
+ background-color: #379B4A;
+ cursor: pointer;
+}
+
+.ui-slider-input &gt; input {
+ margin: 0 10px;
+ padding: 0;
+ width: 50px;
+ text-align: center;
+
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+/*
+ * UI Button
+ */
+
+/* Checkbox */
+
+.ui-checkbox {
+ text-align: center;
+ font-size: 16px;
+ font-family: "Segoe UI", Arial, Helvetica, sans-serif;
+ line-height: 1.5em;
+ color: #FFF;
+
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.ui-checkbox &gt; input {
+ display: none;
+}
+
+.ui-checkbox &gt; label {
+ font-size: 12px;
+ padding: 0.333em 1.666em 0.5em;
+ height: 1em;
+ line-height: 1em;
+
+ background-color: #888;
+ background-image: url("https://mdn.mozillademos.org/files/5683/disabled.png");
+ background-position: center center;
+ background-repeat: no-repeat;
+
+ color: #FFF;
+ border-radius: 3px;
+ font-weight: bold;
+ float: left;
+}
+
+.ui-checkbox .text {
+ padding-left: 34px;
+ background-position: center left 10px;
+}
+
+.ui-checkbox .left {
+ padding-right: 34px;
+ padding-left: 1.666em;
+ background-position: center right 10px;
+}
+
+.ui-checkbox &gt; label:hover {
+ cursor: pointer;
+}
+
+.ui-checkbox &gt; input:checked + label {
+ background-image: url("https://mdn.mozillademos.org/files/5681/checked.png");
+ background-color: #379B4A;
+}
+
+/*
+ * BOX SHADOW GENERATOR TOOL
+ */
+
+body {
+ max-width: 1000px;
+ height: 800px;
+ margin: 20px auto 0;
+
+ font-family: "Segoe UI", Arial, Helvetica, sans-serif;
+
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+}
+
+#container {
+ width: 100%;
+ padding: 2px;
+
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+
+/* container with shadows stacks */
+#stack_container {
+ height: 400px;
+ overflow: hidden;
+ position: relative;
+ border: 1px solid #CCC;
+ border-radius: 3px;
+
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+#stack_container .container {
+ height: 100%;
+ width: 100%;
+ position: absolute;
+ left: 100%;
+ transition-property: left;
+ transition-duration: 0.5s;
+
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+
+#stack_container .title {
+ text-align: center;
+ font-weight: bold;
+ line-height: 2em;
+ border-bottom: 1px solid #43A6E1;
+ color: #666;
+}
+
+
+/*
+ * Stack of Layers for shadow
+ */
+
+#layer_manager {
+ width: 17%;
+ background-color: #FEFEFE;
+ margin: 0 1% 0 0;
+
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ float: left;
+}
+
+
+#layer_manager .button {
+ width: 30%;
+ height: 25px;
+ margin:0 0 10px;
+ color: #333;
+ background-color: #EEE;
+ text-align: center;
+ font-size: 0.75em;
+ line-height: 1.5em;
+ border: 1px solid #CCC;
+ border-radius: 3px;
+
+ display: block;
+ background-position: center center;
+ background-repeat: no-repeat;
+
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ float: left;
+}
+
+#layer_manager .button:hover {
+ background-color: #3380C4;
+ border: 1px solid #3380C4;
+ cursor: pointer;
+}
+
+#layer_manager [data-type='add'] {
+ background-image: url("https://mdn.mozillademos.org/files/5685/add-black.png");
+}
+
+#layer_manager [data-type='add']:hover {
+ background-image: url("https://mdn.mozillademos.org/files/5687/add-white.png");
+}
+
+#layer_manager [data-type='move-up'] {
+ background-image: url("https://mdn.mozillademos.org/files/5697/up-black.png");
+ margin-left: 5%;
+ margin-right: 5%;
+}
+
+#layer_manager [data-type='move-up']:hover {
+ background-image: url("https://mdn.mozillademos.org/files/5709/up-white.png");
+}
+
+#layer_manager [data-type='move-down'] {
+ background-image: url("https://mdn.mozillademos.org/files/5693/down-black.png");
+}
+
+#layer_manager [data-type='move-down']:hover {
+ background-image: url("https://mdn.mozillademos.org/files/5695/down-white.png");
+}
+
+/* shadows classes */
+
+#layer_manager .node {
+ width: 100%;
+ margin: 5px 0;
+ padding: 5px;
+ text-align: center;
+ background-color: #EEE;
+ border: 1px solid #DDD;
+ font-size: 0.75em;
+ line-height: 1.5em;
+ color: #333;
+ border-radius: 3px;
+
+ position: relative;
+ display: block;
+
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+#layer_manager .node:hover {
+ color: #FFF;
+ background-color: #3380C4;
+ cursor: pointer;
+}
+
+/* active element styling */
+
+#layer_manager [data-active='layer'] {
+ color: #FFF;
+ border: none;
+ background-color: #379B4A;
+}
+
+#layer_manager [data-active='subject'] {
+ color: #FFF;
+ background-color: #467FC9;
+}
+
+/* delete button */
+
+#layer_manager .delete {
+ width: 1.5em;
+ height: 100%;
+ float: right;
+ border-radius: 3px;
+ background-image: url("https://mdn.mozillademos.org/files/5689/delete-white.png");
+ background-position: center center;
+ background-repeat: no-repeat;
+ position: absolute;
+ top: 0;
+ right: 10px;
+ display: none;
+}
+
+#layer_manager .delete:hover {
+ background-image: url("https://mdn.mozillademos.org/files/5691/delete-yellow.png");
+}
+
+#layer_manager .node:hover .delete {
+ display: block;
+}
+
+
+#layer_manager .stack {
+ padding: 0 5px;
+ max-height: 90%;
+ overflow: auto;
+ overflow-x: hidden;
+}
+
+
+/*
+ * Layer Menu
+ */
+
+#layer_menu {
+ margin: 0 0 10px 0;
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+#layer_menu .button {
+ width: 100px;
+ margin: 0 5px 0 0;
+ padding: 2.5px;
+ color: #333;
+ background-color: #EEE;
+ border: 1px solid #CCC;
+ border-radius: 3px;
+ text-align: center;
+ font-size: 0.75em;
+ line-height: 1.5em;
+
+ position: relative;
+ display: block;
+ float: left;
+
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+#layer_menu .button:hover {
+ color: #FFF;
+ background-color: #3380C4;
+ border: 1px solid #3380C4;
+ cursor: pointer;
+}
+
+#layer_menu .delete {
+ width: 1.5em;
+ height: 100%;
+ float: right;
+ border-radius: 3px;
+ background-image: url("https://mdn.mozillademos.org/files/5689/delete-white.png");
+ background-position: center center;
+ background-repeat: no-repeat;
+ position: absolute;
+ top: 0;
+ right: 5px;
+ display: none;
+}
+
+#layer_menu .delete:hover {
+ background-image: url("https://mdn.mozillademos.org/files/5691/delete-yellow.png");
+}
+
+#layer_menu .button:hover .delete {
+ display: block;
+}
+
+
+/*
+ * active element styling
+ */
+
+#layer_menu [data-active='subject'] {
+ color: #FFF;
+ background-color: #379B4A;
+ border: 1px solid #379B4A;
+}
+
+
+/* Checkbox */
+
+#layer_menu .ui-checkbox &gt; label {
+ height: 15px;
+ line-height: 17px;
+ font-weight: normal;
+ width: 46px;
+ margin: 0 5px 0 0;
+}
+
+#layer_menu .ui-checkbox &gt; input:checked + label {
+ display: none;
+}
+
+
+/******************************************************************************/
+/******************************************************************************/
+/*
+ * Preview Area
+ */
+
+#preview_zone {
+ width: 82%;
+ float: left;
+
+}
+
+
+#preview {
+ width: 100%;
+ height: 400px;
+ border: 1px solid #CCC;
+ border-radius: 3px;
+ text-align: center;
+
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ cursor: move;
+ float: left;
+}
+
+#preview .content {
+ width: 100%;
+ height: 100%;
+ display: block;
+}
+
+#obj-element {
+ width: 300px;
+ height: 100px;
+ border: 1px solid #CCC;
+ background: #FFF;
+ position: relative;
+}
+
+
+#obj-before {
+ height: 100%;
+ width: 100%;
+ background: #999;
+ border: 1px solid #CCC;
+ text-align: left;
+ display : block;
+ position: absolute;
+ z-index: -1;
+}
+
+#obj-after {
+ height: 100%;
+ width: 100%;
+ background: #DDD;
+ border: 1px solid #CCC;
+ text-align: right;
+ display : block;
+ position: absolute;
+ z-index: -1;
+}
+
+
+/******************************************************************************/
+/******************************************************************************/
+
+/**
+ * Controls
+ */
+
+.wrap-left {
+ float: left;
+ overflow: hidden;
+}
+
+.wrap-right {
+ float: right;
+ overflow: hidden;
+}
+
+.wrap-left &gt; * {
+ float: left;
+}
+
+.wrap-right &gt; * {
+ float: right;
+}
+
+@media (min-width: 960px) {
+
+ .wrap-left {
+ width: 45%;
+ }
+
+ .wrap-right {
+ width: 55%;
+ }
+}
+
+
+@media (max-width: 959px) {
+
+ .wrap-left {
+ width: 30%;
+ }
+
+ .wrap-right {
+ width: 70%;
+ }
+}
+
+
+#controls {
+ color: #444;
+ margin: 10px 0 0 0;
+}
+
+
+#controls .category {
+ width: 500px;
+ margin: 0 auto 20px;
+ padding: 0;
+
+}
+
+#controls .category .title {
+ width: 100%;
+ height: 1.5em;
+ line-height: 1.5em;
+ color: #AAA;
+ text-align: right;
+}
+
+#controls .category &gt; .group {
+ border: 1px solid #CCC;
+ border-radius: 3px;
+}
+
+
+/**
+ * Color Picker
+ */
+
+@media (min-width: 960px) {
+ #controls .colorpicker {
+ width: 420px;
+ }
+}
+
+@media (max-width: 959px) {
+ #controls .colorpicker {
+ width: 210px;
+ }
+}
+
+#colorpicker {
+ width: 100%;
+ margin: 0 auto;
+}
+
+#colorpicker .gradient {
+ width: 200px;
+ height: 200px;
+ margin: 5px;
+ background: url("https://mdn.mozillademos.org/files/5707/picker_mask_200.png");
+ background: -moz-linear-gradient(bottom, #000 0%, rgba(0, 0, 0, 0) 100%),
+ -moz-linear-gradient(left, #FFF 0%, rgba(255, 255, 255, 0) 100%);
+ background: -webkit-linear-gradient(bottom, #000 0%, rgba(0, 0, 0, 0) 100%),
+ -webkit-linear-gradient(left, #FFF 0%, rgba(255, 255, 255, 0) 100%);
+ background-color: #F00;
+ float: left;
+}
+
+#colorpicker .hue {
+ width: 200px;
+ height: 30px;
+ margin: 5px;
+ background: url("https://mdn.mozillademos.org/files/5701/hue.png");
+ background: -moz-linear-gradient(left, #F00 0%, #FF0 16.66%, #0F0 33.33%, #0FF 50%,
+ #00F 66.66%, #F0F 83.33%, #F00 100%);
+ background: -webkit-linear-gradient(left, #F00 0%, #FF0 16.66%, #0F0 33.33%, #0FF 50%,
+ #00F 66.66%, #F0F 83.33%, #F00 100%);
+ float: left;
+}
+
+#colorpicker .alpha {
+ width: 200px;
+ height: 30px;
+ margin: 5px;
+ border: 1px solid #CCC;
+ float: left;
+ background: url("https://mdn.mozillademos.org/files/5705/alpha.png");
+
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+#colorpicker #alpha {
+ width: 100%;
+ height: 100%;
+ background: url("https://mdn.mozillademos.org/files/5703/alpha_mask.png");
+ background: -moz-linear-gradient(left, rgba(255, 0, 0, 0) 0%, rgba(255, 0, 0, 1) 100%);
+}
+
+#colorpicker #gradient_picker {
+ width: 0.5em;
+ height: 0.5em;
+ border-radius: 0.4em;
+ border: 2px solid #CCC;
+ position: relative;
+ top: 20%;
+ left: 20%;
+}
+
+#colorpicker #hue_selector,
+#colorpicker #alpha_selector {
+ width: 3px;
+ height: 100%;
+ border: 1px solid #777;
+ background-color: #FFF;
+ position: relative;
+ top: -1px;
+ left: 0%;
+}
+
+/* input HSV and RGB */
+#colorpicker .info {
+ width: 200px;
+ margin: 5px;
+ float: left;
+}
+
+#colorpicker .info * {
+ float: left;
+}
+
+#colorpicker .info input {
+ margin: 0;
+ text-align: center;
+ width: 30px;
+ -moz-user-select: text;
+ -webkit-user-select: text;
+ -ms-user-select: text;
+}
+
+#colorpicker .info span {
+ height: 20px;
+ width: 30px;
+ text-align: center;
+ line-height: 20px;
+ display: block;
+}
+
+/* Preview color */
+#colorpicker .block {
+ width: 95px;
+ height: 54px;
+ float: left;
+ position: relative;
+}
+
+#colorpicker .preview {
+ margin: 5px;
+ border: 1px solid #CCC;
+ background-image: url("https://mdn.mozillademos.org/files/5705/alpha.png");
+
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+#colorpicker .preview:before {
+ height: 100%;
+ width: 50%;
+ left: 50%;
+ content: "";
+ background: #FFF;
+ position: absolute;
+ z-index: 1;
+}
+
+#colorpicker .preview &gt; * {
+ width: 50%;
+ height: 100%;
+}
+
+#colorpicker #output_color {
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ z-index: 2;
+}
+
+#colorpicker .block .input {
+ float: right;
+}
+
+#colorpicker [data-topic="a"] &gt; span {
+ width: 50px;
+}
+
+#colorpicker [data-topic="hexa"] {
+ float: right;
+ margin: 10px 0 0 0;
+}
+
+#colorpicker [data-topic="hexa"] &gt; span {
+ display: none;
+}
+
+#colorpicker [data-topic="hexa"] &gt; input {
+ width: 85px;
+ padding: 2px 0;
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+
+/*
+ * UI Components
+ */
+
+/* Property */
+
+.property {
+ height: 20px;
+ margin: 10px 0;
+}
+
+.property * {
+ float: left;
+ height: 100%;
+ line-height: 100%;
+}
+
+/* Slider */
+
+#controls .ui-slider-name {
+ margin: 0 10px 0 0;
+}
+
+/*
+ * Output code styling
+ */
+
+#output {
+ position: relative;
+}
+
+#output .menu {
+ max-width: 70%;
+ height: 20px;
+ position: absolute;
+ top: 2px;
+}
+
+#output .button {
+ width: 90px;
+ height: 22px;
+ margin: 0 5px 0 0;
+ text-align: center;
+ line-height: 20px;
+ font-size: 14px;
+ color: #FFF;
+ background-color: #999;
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+ bottom: -5px;
+ float:left;
+}
+
+#output .button:hover {
+ color: #FFF;
+ background-color: #666;
+ cursor: pointer;
+}
+
+#output .menu [data-active="true"] {
+ color: #777;
+ background-color: #FFF;
+ border: 1px solid #CCC;
+ border-bottom: none;
+}
+
+#output .menu [data-topic="before"] {
+ left: 100px;
+}
+
+#output .menu [data-topic="after"] {
+ left: 200px;
+}
+
+#output .output {
+ width: 480px;
+ margin: 10px;
+ padding: 10px;
+ overflow: hidden;
+ color: #555;
+ font-size: 14px;
+ border: 1px dashed #CCC;
+ border-radius: 3px;
+ display: none;
+
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+
+ -moz-user-select: text;
+ -webkit-user-select: text;
+ -ms-user-select: text;
+}
+
+#output .css-property {
+ width: 100%;
+ float: left;
+ white-space: pre;
+}
+
+#output .name {
+ width: 35%;
+ float: left;
+}
+
+#output .value {
+ width: 65%;
+ float: left;
+}
+
+</pre>
+
+<h3 id="JavaScript_Content">JavaScript Content</h3>
+
+<pre class="brush: js"><code class="language-js">
+
+'use strict';
+
+/**
+ * UI-SlidersManager
+ */
+
+var SliderManager = (function SliderManager() {
+
+ var subscribers = {};
+ var sliders = [];
+
+ var Slider = function(node) {
+ var min = node.getAttribute('data-min') | 0;
+ var max = node.getAttribute('data-max') | 0;
+ var step = node.getAttribute('data-step') | 0;
+ var value = node.getAttribute('data-value') | 0;
+ var snap = node.getAttribute('data-snap');
+ var topic = node.getAttribute('data-topic');
+
+ this.min = min;
+ this.max = max &gt; 0 ? max : 100;
+ this.step = step === 0 ? 1 : step;
+ this.value = value &lt;= max &amp;&amp; value &gt;= min ? value : (min + max) / 2 | 0;
+ this.snap = snap === "true" ? true : false;
+ this.topic = topic;
+ this.node = node;
+
+ var pointer = document.createElement('div');
+ pointer.className = 'ui-slider-pointer';
+ node.appendChild(pointer);
+ this.pointer = pointer;
+
+ setMouseTracking(node, updateSlider.bind(this));
+
+ sliders[topic] = this;
+ setValue(topic, this.value);
+ }
+
+ var setButtonComponent = function setButtonComponent(node) {
+ var type = node.getAttribute('data-type');
+ var topic = node.getAttribute('data-topic');
+ if (type === "sub") {
+ node.textContent = '-';
+ node.addEventListener("click", function() {
+ decrement(topic);
+ });
+ }
+ if (type === "add") {
+ node.textContent = '+';
+ node.addEventListener("click", function() {
+ increment(topic);
+ });
+ }
+ }
+
+ var setInputComponent = function setInputComponent(node) {
+ var topic = node.getAttribute('data-topic');
+ var unit_type = node.getAttribute('data-unit');
+
+ var input = document.createElement('input');
+ var unit = document.createElement('span');
+ unit.textContent = unit_type;
+
+ input.setAttribute('type', 'text');
+ node.appendChild(input);
+ node.appendChild(unit);
+
+ input.addEventListener('click', function(e) {
+ this.select();
+ });
+
+ input.addEventListener('change', function(e) {
+ setValue(topic, e.target.value | 0);
+ });
+
+ subscribe(topic, function(value) {
+ node.children[0].value = value;
+ });
+ }
+
+ var increment = function increment(topic) {
+ var slider = sliders[topic];
+ if (slider === null || slider === undefined)
+ return;
+
+ if (slider.value + slider.step &lt;= slider.max) {
+ slider.value += slider.step;
+ setValue(slider.topic, slider.value)
+ notify.call(slider);
+ }
+ };
+
+ var decrement = function decrement(topic) {
+ var slider = sliders[topic];
+ if (slider === null || slider === undefined)
+ return;
+
+ if (slider.value - slider.step &gt;= slider.min) {
+ slider.value -= slider.step;
+ setValue(topic, slider.value)
+ notify.call(slider);
+ }
+ }
+
+ // this = Slider object
+ var updateSlider = function updateSlider(e) {
+ var node = this.node;
+ var pos = e.pageX - node.offsetLeft;
+ var width = node.clientWidth;
+ var delta = this.max - this.min;
+ var offset = this.pointer.clientWidth + 4; // border width * 2
+
+ if (pos &lt; 0) pos = 0;
+ if (pos &gt; width) pos = width;
+
+ var value = pos * delta / width | 0;
+ var precision = value % this.step;
+ value = value - precision + this.min;
+ if (precision &gt; this.step / 2)
+ value = value + this.step;
+
+ if (this.snap)
+ pos = (value - this.min) * width / delta;
+
+ this.pointer.style.left = pos - offset/2 + "px";
+ this.value = value;
+ node.setAttribute('data-value', value);
+ notify.call(this);
+ }
+
+ var setValue = function setValue(topic, value) {
+ var slider = sliders[topic];
+
+ if (value &gt; slider.max || value &lt; slider.min)
+ return;
+
+ var delta = slider.max - slider.min;
+ var width = slider.node.clientWidth;
+ var offset = slider.pointer.clientWidth;
+ var pos = (value - slider.min) * width / delta;
+ slider.value = value;
+ slider.pointer.style.left = pos - offset / 2 + "px";
+ slider.node.setAttribute('data-value', value);
+ notify.call(slider);
+ }
+
+ var setMouseTracking = function setMouseTracking(elem, callback) {
+ elem.addEventListener("mousedown", function(e) {
+ callback(e);
+ document.addEventListener("mousemove", callback);
+ });
+
+ document.addEventListener("mouseup", function(e) {
+ document.removeEventListener("mousemove", callback);
+ });
+ }
+
+ var subscribe = function subscribe(topic, callback) {
+ if (subscribers[topic] === undefined)
+ subscribers[topic] = [];
+ subscribers[topic].push(callback);
+ }
+
+ var unsubscribe = function unsubscribe(topic, callback) {
+ subscribers[topic].indexOf(callback);
+ subscribers[topic].splice(index, 1);
+ }
+
+ var notify = function notify() {
+ if (subscribers[this.topic] === undefined)
+ return;
+
+ for (var i in subscribers[this.topic]) {
+ subscribers[this.topic][i](this.value);
+ }
+ }
+
+ var init = function init() {
+ var elem, size;
+
+ elem = document.querySelectorAll('.ui-slider-btn-set');
+ size = elem.length;
+ for (var i = 0; i &lt; size; i++)
+ setButtonComponent(elem[i]);
+
+ elem = document.querySelectorAll('.ui-slider-input');
+ size = elem.length;
+ for (var i = 0; i &lt; size; i++)
+ setInputComponent(elem[i]);
+
+ elem = document.querySelectorAll('.ui-slider');
+ size = elem.length;
+ for (var i = 0; i &lt; size; i++)
+ new Slider(elem[i]);
+ }
+
+ return {
+ init : init,
+ setValue : setValue,
+ subscribe : subscribe,
+ unsubscribe : unsubscribe
+ }
+
+})();
+
+/**
+ * UI-ButtonManager
+ */
+
+var ButtonManager = (function CheckBoxManager() {
+
+ var subscribers = [];
+ var buttons = [];
+
+ var CheckBox = function CheckBox(node) {
+ var topic = node.getAttribute('data-topic');
+ var state = node.getAttribute('data-state');
+ var name = node.getAttribute('data-label');
+ var align = node.getAttribute('data-text-on');
+
+ state = (state === "true");
+
+ var checkbox = document.createElement("input");
+ var label = document.createElement("label");
+
+ var id = 'checkbox-' + topic;
+ checkbox.id = id;
+ checkbox.setAttribute('type', 'checkbox');
+ checkbox.checked = state;
+
+ label.setAttribute('for', id);
+ if (name) {
+ label.className = 'text';
+ if (align)
+ label.className += ' ' + align;
+ label.textContent = name;
+ }
+
+ node.appendChild(checkbox);
+ node.appendChild(label);
+
+ this.node = node;
+ this.topic = topic;
+ this.checkbox = checkbox;
+
+ checkbox.addEventListener('change', function(e) {
+ notify.call(this);
+ }.bind(this));
+
+ buttons[topic] = this;
+ }
+
+ var getNode = function getNode(topic) {
+ return buttons[topic].node;
+ }
+
+ var setValue = function setValue(topic, value) {
+ try {
+ buttons[topic].checkbox.checked = value;
+ notify.call(buttons[topic]);
+ }
+ catch(error) {
+ console.log(error, topic, value);
+ }
+ }
+
+ var subscribe = function subscribe(topic, callback) {
+ if (subscribers[topic] === undefined)
+ subscribers[topic] = [];
+
+ subscribers[topic].push(callback);
+ }
+
+ var unsubscribe = function unsubscribe(topic, callback) {
+ subscribers[topic].indexOf(callback);
+ subscribers[topic].splice(index, 1);
+ }
+
+ var notify = function notify() {
+ if (subscribers[this.topic] === undefined)
+ return;
+ for (var i = 0; i &lt; subscribers[this.topic].length; i++)
+ subscribers[this.topic][i](this.checkbox.checked);
+ }
+
+ var init = function init() {
+ var elem = document.querySelectorAll('.ui-checkbox');
+ var size = elem.length;
+ for (var i = 0; i &lt; size; i++)
+ new CheckBox(elem[i]);
+ }
+
+ return {
+ init : init,
+ setValue : setValue,
+ subscribe : subscribe,
+ unsubscribe : unsubscribe
+ }
+
+})();
+
+
+window.addEventListener("load", function(){
+ BoxShadow.init();
+});
+
+var BoxShadow = (function BoxShadow() {
+
+ function getElemById(id) {
+ return document.getElementById(id);
+ }
+
+ /**
+ * RGBA Color class
+ */
+
+ function Color() {
+ this.r = 0;
+ this.g = 0;
+ this.b = 0;
+ this.a = 1;
+ this.hue = 0;
+ this.saturation = 0;
+ this.value = 0;
+ }
+
+ Color.prototype.copy = function copy(obj) {
+ if(obj instanceof Color !== true) {
+ console.log("Typeof instance not Color");
+ return;
+ }
+
+ this.r = obj.r;
+ this.g = obj.g;
+ this.b = obj.b;
+ this.a = obj.a;
+ this.hue = obj.hue;
+ this.saturation = obj.saturation;
+ this.value = obj.value;
+ }
+
+ Color.prototype.setRGBA = function setRGBA(red, green, blue, alpha) {
+ if (red != undefined)
+ this.r = red | 0;
+ if (green != undefined)
+ this.g = green | 0;
+ if (blue != undefined)
+ this.b = blue | 0;
+ if (alpha != undefined)
+ this.a = alpha | 0;
+ }
+
+ /**
+ * HSV/HSB (hue, saturation, value / brightness)
+ * @param hue 0-360
+ * @param saturation 0-100
+ * @param value 0-100
+ */
+ Color.prototype.setHSV = function setHSV(hue, saturation, value) {
+ this.hue = hue;
+ this.saturation = saturation;
+ this.value = value;
+ this.updateRGB();
+ }
+
+ Color.prototype.updateRGB = function updateRGB() {
+ var sat = this.saturation / 100;
+ var value = this.value / 100;
+ var C = sat * value;
+ var H = this.hue / 60;
+ var X = C * (1 - Math.abs(H % 2 - 1));
+ var m = value - C;
+ var precision = 255;
+
+ C = (C + m) * precision;
+ X = (X + m) * precision;
+ m = m * precision;
+
+ if (H &gt;= 0 &amp;&amp; H &lt; 1) { this.setRGBA(C, X, m); return; }
+ if (H &gt;= 1 &amp;&amp; H &lt; 2) { this.setRGBA(X, C, m); return; }
+ if (H &gt;= 2 &amp;&amp; H &lt; 3) { this.setRGBA(m, C, X); return; }
+ if (H &gt;= 3 &amp;&amp; H &lt; 4) { this.setRGBA(m, X, C); return; }
+ if (H &gt;= 4 &amp;&amp; H &lt; 5) { this.setRGBA(X, m, C); return; }
+ if (H &gt;= 5 &amp;&amp; H &lt; 6) { this.setRGBA(C, m, X); return; }
+ }
+
+ Color.prototype.updateHSV = function updateHSV() {
+ var red = this.r / 255;
+ var green = this.g / 255;
+ var blue = this.b / 255;
+
+ var cmax = Math.max(red, green, blue);
+ var cmin = Math.min(red, green, blue);
+ var delta = cmax - cmin;
+ var hue = 0;
+ var saturation = 0;
+
+ if (delta) {
+ if (cmax === red ) { hue = ((green - blue) / delta); }
+ if (cmax === green ) { hue = 2 + (blue - red) / delta; }
+ if (cmax === blue ) { hue = 4 + (red - green) / delta; }
+ if (cmax) saturation = delta / cmax;
+ }
+
+ this.hue = 60 * hue | 0;
+ if (this.hue &lt; 0) this.hue += 360;
+ this.saturation = (saturation * 100) | 0;
+ this.value = (cmax * 100) | 0;
+ }
+
+ Color.prototype.setHexa = function setHexa(value) {
+ var valid = /(^#{0,1}[0-9A-F]{6}$)|(^#{0,1}[0-9A-F]{3}$)/i.test(value)
+ if (valid !== true)
+ return;
+
+ if (value[0] === '#')
+ value = value.slice(1, value.length);
+
+ if (value.length === 3)
+ value = value.replace(/([0-9A-F])([0-9A-F])([0-9A-F])/i,"$1$1$2$2$3$3");
+
+ this.r = parseInt(value.substr(0, 2), 16);
+ this.g = parseInt(value.substr(2, 2), 16);
+ this.b = parseInt(value.substr(4, 2), 16);
+
+ this.alpha = 1;
+ }
+
+ Color.prototype.getHexa = function getHexa() {
+ var r = this.r.toString(16);
+ var g = this.g.toString(16);
+ var b = this.b.toString(16);
+ if (this.r &lt; 16) r = '0' + r;
+ if (this.g &lt; 16) g = '0' + g;
+ if (this.b &lt; 16) b = '0' + b;
+ var value = '#' + r + g + b;
+ return value.toUpperCase();
+ }
+
+ Color.prototype.getRGBA = function getRGBA() {
+
+ var rgb = "(" + this.r + ", " + this.g + ", " + this.b;
+ var a = '';
+ var v = '';
+ if (this.a !== 1) {
+ a = 'a';
+ v = ', ' + this.a;
+ }
+
+ var value = "rgb" + a + rgb + v + ")";
+ return value;
+ }
+
+ Color.prototype.getColor = function getColor() {
+ if (this.a | 0 === 1)
+ return this.getHexa();
+ return this.getRGBA();
+ }
+
+ /**
+ * Shadow Object
+ */
+ function Shadow() {
+ this.inset = false;
+ this.posX = 5;
+ this.posY = -5;
+ this.blur = 5;
+ this.spread = 0;
+ this.color = new Color();
+
+ var hue = (Math.random() * 360) | 0;
+ var saturation = (Math.random() * 75) | 0;
+ var value = (Math.random() * 50 + 50) | 0;
+ this.color.setHSV(hue, saturation, value, 1);
+ }
+
+ Shadow.prototype.computeCSS = function computeCSS() {
+ var value = "";
+ if (this.inset === true)
+ value += "inset ";
+ value += this.posX + "px ";
+ value += this.posY + "px ";
+ value += this.blur + "px ";
+ value += this.spread + "px ";
+ value += this.color.getColor();
+
+ return value;
+ }
+
+ Shadow.prototype.toggleInset = function toggleInset(value) {
+ if (value !== undefined || typeof value === "boolean")
+ this.inset = value;
+ else
+ this.inset = this.inset === true ? false : true;
+ }
+
+ Shadow.prototype.copy = function copy(obj) {
+ if(obj instanceof Shadow !== true) {
+ console.log("Typeof instance not Shadow");
+ return;
+ }
+
+ this.inset = obj.inset;
+ this.posX = obj.posX;
+ this.posY = obj.posY;
+ this.blur = obj.blur;
+ this.spread = obj.spread;
+ this.color.copy(obj.color);
+ }
+
+ /**
+ * Color Picker
+ */
+ var ColoPicker = (function ColoPicker() {
+
+ var colorpicker;
+ var hue_area;
+ var gradient_area;
+ var alpha_area;
+ var gradient_picker;
+ var hue_selector;
+ var alpha_selector;
+ var pick_object;
+ var info_rgb;
+ var info_hsv;
+ var info_hexa;
+ var output_color;
+ var color = new Color();
+ var subscribers = [];
+
+ var updateColor = function updateColor(e) {
+ var x = e.pageX - gradient_area.offsetLeft;
+ var y = e.pageY - gradient_area.offsetTop;
+
+ // width and height should be the same
+ var size = gradient_area.clientWidth;
+
+ if (x &gt; size)
+ x = size;
+ if (y &gt; size)
+ y = size;
+
+ if (x &lt; 0) x = 0;
+ if (y &lt; 0) y = 0;
+
+ var value = 100 - (y * 100 / size) | 0;
+ var saturation = x * 100 / size | 0;
+
+ color.setHSV(color.hue, saturation, value);
+ // should update just
+ // color pointer location
+ updateUI();
+ notify("color", color);
+ }
+
+ var updateHue = function updateHue(e) {
+ var x = e.pageX - hue_area.offsetLeft;
+ var width = hue_area.clientWidth;
+
+ if (x &lt; 0) x = 0;
+ if (x &gt; width) x = width;
+
+ var hue = ((360 * x) / width) | 0;
+ if (hue === 360) hue = 359;
+
+ color.setHSV(hue, color.saturation, color.value);
+
+ // should update just
+ // hue pointer location
+ // picker area background
+ // alpha area background
+ updateUI();
+ notify("color", color);
+ }
+
+ var updateAlpha = function updateAlpha(e) {
+ var x = e.pageX - alpha_area.offsetLeft;
+ var width = alpha_area.clientWidth;
+
+ if (x &lt; 0) x = 0;
+ if (x &gt; width) x = width;
+
+ color.a = (x / width).toFixed(2);
+
+ // should update just
+ // alpha pointer location
+ updateUI();
+ notify("color", color);
+ }
+
+ var setHueGfx = function setHueGfx(hue) {
+ var sat = color.saturation;
+ var val = color.value;
+ var alpha = color.a;
+
+ color.setHSV(hue, 100, 100);
+ gradient_area.style.backgroundColor = color.getHexa();
+
+ color.a = 0;
+ var start = color.getRGBA();
+ color.a = 1;
+ var end = color.getRGBA();
+ color.a = alpha;
+
+ var gradient = '-moz-linear-gradient(left, ' + start + '0%, ' + end + ' 100%)';
+ alpha_area.style.background = gradient;
+ }
+
+ var updateUI = function updateUI() {
+ var x, y; // coordinates
+ var size; // size of the area
+ var offset; // pointer graphic selector offset
+
+ // Set color pointer location
+ size = gradient_area.clientWidth;
+ offset = gradient_picker.clientWidth / 2 + 2;
+
+ x = (color.saturation * size / 100) | 0;
+ y = size - (color.value * size / 100) | 0;
+
+ gradient_picker.style.left = x - offset + "px";
+ gradient_picker.style.top = y - offset + "px";
+
+ // Set hue pointer location
+ size = hue_area.clientWidth;
+ offset = hue_selector.clientWidth/2;
+ x = (color.hue * size / 360 ) | 0;
+ hue_selector.style.left = x - offset + "px";
+
+ // Set alpha pointer location
+ size = alpha_area.clientWidth;
+ offset = alpha_selector.clientWidth/2;
+ x = (color.a * size) | 0;
+ alpha_selector.style.left = x - offset + "px";
+
+ // Set picker area background
+ var nc = new Color();
+ nc.copy(color);
+ if (nc.hue === 360) nc.hue = 0;
+ nc.setHSV(nc.hue, 100, 100);
+ gradient_area.style.backgroundColor = nc.getHexa();
+
+ // Set alpha area background
+ nc.copy(color);
+ nc.a = 0;
+ var start = nc.getRGBA();
+ nc.a = 1;
+ var end = nc.getRGBA();
+ var gradient = '-moz-linear-gradient(left, ' + start + '0%, ' + end + ' 100%)';
+ alpha_area.style.background = gradient;
+
+ // Update color info
+ notify("color", color);
+ notify("hue", color.hue);
+ notify("saturation", color.saturation);
+ notify("value", color.value);
+ notify("r", color.r);
+ notify("g", color.g);
+ notify("b", color.b);
+ notify("a", color.a);
+ notify("hexa", color.getHexa());
+ output_color.style.backgroundColor = color.getRGBA();
+ }
+
+ var setInputComponent = function setInputComponent(node) {
+ var topic = node.getAttribute('data-topic');
+ var title = node.getAttribute('data-title');
+ var action = node.getAttribute('data-action');
+ title = title === null ? '' : title;
+
+ var input = document.createElement('input');
+ var info = document.createElement('span');
+ info.textContent = title;
+
+ input.setAttribute('type', 'text');
+ input.setAttribute('data-action', 'set-' + action + '-' + topic);
+ node.appendChild(info);
+ node.appendChild(input);
+
+ input.addEventListener('click', function(e) {
+ this.select();
+ });
+
+ input.addEventListener('change', function(e) {
+ if (action === 'HSV')
+ inputChangeHSV(topic);
+ if (action === 'RGB')
+ inputChangeRGB(topic);
+ if (action === 'alpha')
+ inputChangeAlpha(topic);
+ if (action === 'hexa')
+ inputChangeHexa(topic);
+ });
+
+ subscribe(topic, function(value) {
+ node.children[1].value = value;
+ });
+ }
+
+ var inputChangeHSV = function actionHSV(topic) {
+ var selector = "[data-action='set-HSV-" + topic + "']";
+ var node = document.querySelector("#colorpicker " + selector);
+ var value = parseInt(node.value);
+
+ if (typeof value === 'number' &amp;&amp; isNaN(value) === false &amp;&amp;
+ value &gt;= 0 &amp;&amp; value &lt; 360)
+ color[topic] = value;
+
+ color.updateRGB();
+ updateUI();
+ }
+
+ var inputChangeRGB = function inputChangeRGB(topic) {
+ var selector = "[data-action='set-RGB-" + topic + "']";
+ var node = document.querySelector("#colorpicker " + selector);
+ var value = parseInt(node.value);
+
+ if (typeof value === 'number' &amp;&amp; isNaN(value) === false &amp;&amp;
+ value &gt;= 0 &amp;&amp; value &lt;= 255)
+ color[topic] = value;
+
+ color.updateHSV();
+ updateUI();
+ }
+
+ var inputChangeAlpha = function inputChangeAlpha(topic) {
+ var selector = "[data-action='set-alpha-" + topic + "']";
+ var node = document.querySelector("#colorpicker " + selector);
+ var value = parseFloat(node.value);
+
+ if (typeof value === 'number' &amp;&amp; isNaN(value) === false &amp;&amp;
+ value &gt;= 0 &amp;&amp; value &lt;= 1)
+ color.a = value.toFixed(2);
+
+ updateUI();
+ }
+
+ var inputChangeHexa = function inputChangeHexa(topic) {
+ var selector = "[data-action='set-hexa-" + topic + "']";
+ var node = document.querySelector("#colorpicker " + selector);
+ var value = node.value;
+ color.setHexa(value);
+ color.updateHSV();
+ updateUI();
+ }
+
+ var setMouseTracking = function setMouseTracking(elem, callback) {
+
+ elem.addEventListener("mousedown", function(e) {
+ callback(e);
+ document.addEventListener("mousemove", callback);
+ });
+
+ document.addEventListener("mouseup", function(e) {
+ document.removeEventListener("mousemove", callback);
+ });
+ }
+
+ /*
+ * Observer
+ */
+ var setColor = function setColor(obj) {
+ if(obj instanceof Color !== true) {
+ console.log("Typeof instance not Color");
+ return;
+ }
+ color.copy(obj);
+ updateUI();
+ }
+
+ var subscribe = function subscribe(topic, callback) {
+ if (subscribers[topic] === undefined)
+ subscribers[topic] = [];
+
+ subscribers[topic].push(callback);
+ }
+
+ var unsubscribe = function unsubscribe(callback) {
+ subscribers.indexOf(callback);
+ subscribers.splice(index, 1);
+ }
+
+ var notify = function notify(topic, value) {
+ for (var i in subscribers[topic])
+ subscribers[topic][i](value);
+ }
+
+ var init = function init() {
+ colorpicker = getElemById("colorpicker");
+ hue_area = getElemById("hue");
+ gradient_area = getElemById("gradient");
+ alpha_area = getElemById("alpha");
+ gradient_picker = getElemById("gradient_picker");
+ hue_selector = getElemById("hue_selector");
+ alpha_selector = getElemById("alpha_selector");
+ output_color = getElemById("output_color");
+
+ var elem = document.querySelectorAll('#colorpicker .input');
+ var size = elem.length;
+ for (var i = 0; i &lt; size; i++)
+ setInputComponent(elem[i]);
+
+ setMouseTracking(gradient_area, updateColor);
+ setMouseTracking(hue_area, updateHue);
+ setMouseTracking(alpha_area, updateAlpha);
+
+ }
+
+ return {
+ init : init,
+ setColor : setColor,
+ subscribe : subscribe,
+ unsubscribe : unsubscribe
+ }
+
+ })();
+
+ /**
+ * Shadow dragging
+ */
+ var PreviewMouseTracking = (function Drag() {
+ var active = false;
+ var lastX = 0;
+ var lastY = 0;
+ var subscribers = [];
+
+ var init = function init(id) {
+ var elem = getElemById(id);
+ elem.addEventListener('mousedown', dragStart, false);
+ document.addEventListener('mouseup', dragEnd, false);
+ }
+
+ var dragStart = function dragStart(e) {
+ if (e.button !== 0)
+ return;
+
+ active = true;
+ lastX = e.clientX;
+ lastY = e.clientY;
+ document.addEventListener('mousemove', mouseDrag, false);
+ }
+
+ var dragEnd = function dragEnd(e) {
+ if (e.button !== 0)
+ return;
+
+ if (active === true) {
+ active = false;
+ document.removeEventListener('mousemove', mouseDrag, false);
+ }
+ }
+
+ var mouseDrag = function mouseDrag(e) {
+ notify(e.clientX - lastX, e.clientY - lastY);
+ lastX = e.clientX;
+ lastY = e.clientY;
+ }
+
+ var subscribe = function subscribe(callback) {
+ subscribers.push(callback);
+ }
+
+ var unsubscribe = function unsubscribe(callback) {
+ var index = subscribers.indexOf(callback);
+ subscribers.splice(index, 1);
+ }
+
+ var notify = function notify(deltaX, deltaY) {
+ for (var i in subscribers)
+ subscribers[i](deltaX, deltaY);
+ }
+
+ return {
+ init : init,
+ subscribe : subscribe,
+ unsubscribe : unsubscribe
+ }
+
+ })();
+
+ /*
+ * Element Class
+ */
+ var CssClass = function CssClass(id) {
+ this.left = 0;
+ this.top = 0;
+ this.rotate = 0;
+ this.width = 300;
+ this.height = 100;
+ this.display = true;
+ this.border = true;
+ this.zIndex = -1;
+ this.bgcolor = new Color();
+ this.id = id;
+ this.node = getElemById('obj-' + id);
+ this.object = getElemById(id);
+ this.shadowID = null;
+ this.shadows = []
+ this.render = [];
+ this.init();
+ }
+
+ CssClass.prototype.init = function init() {
+ this.left = ((this.node.parentNode.clientWidth - this.node.clientWidth) / 2) | 0;
+ this.top = ((this.node.parentNode.clientHeight - this.node.clientHeight) / 2) | 0;
+
+ this.setTop(this.top);
+ this.setLeft(this.left);
+ this.setHeight(this.height);
+ this.setWidth(this.width);
+ this.bgcolor.setHSV(0, 0, 100);
+ this.updateBgColor(this.bgcolor);
+ }
+
+ CssClass.prototype.updatePos = function updatePos(deltaX, deltaY) {
+ this.left += deltaX;
+ this.top += deltaY;
+ this.node.style.top = this.top + "px";
+ this.node.style.left = this.left + "px";
+ SliderManager.setValue("left", this.left);
+ SliderManager.setValue("top", this.top);
+ }
+
+ CssClass.prototype.setLeft = function setLeft(value) {
+ this.left = value;
+ this.node.style.left = this.left + "px";
+ OutputManager.updateProperty(this.id, 'left', this.left + 'px');
+ }
+
+ CssClass.prototype.setTop = function setTop(value) {
+ this.top = value;
+ this.node.style.top = this.top + 'px';
+ OutputManager.updateProperty(this.id, 'top', this.top + 'px');
+ }
+
+ CssClass.prototype.setWidth = function setWidth(value) {
+ this.width = value;
+ this.node.style.width = this.width + 'px';
+ OutputManager.updateProperty(this.id, 'width', this.width + 'px');
+ }
+
+ CssClass.prototype.setHeight = function setHeight(value) {
+ this.height = value;
+ this.node.style.height = this.height + 'px';
+ OutputManager.updateProperty(this.id, 'height', this.height + 'px');
+ }
+
+ // Browser support
+ CssClass.prototype.setRotate = function setRotate(value) {
+ var cssvalue = 'rotate(' + value +'deg)';
+
+ this.node.style.transform = cssvalue;
+ this.node.style.webkitTransform = cssvalue;
+ this.node.style.msTransform = cssvalue;
+
+ if (value !== 0) {
+ if (this.rotate === 0) {
+ OutputManager.toggleProperty(this.id, 'transform', true);
+ OutputManager.toggleProperty(this.id, '-webkit-transform', true);
+ OutputManager.toggleProperty(this.id, '-ms-transform', true);
+ }
+ }
+ else {
+ OutputManager.toggleProperty(this.id, 'transform', false);
+ OutputManager.toggleProperty(this.id, '-webkit-transform', false);
+ OutputManager.toggleProperty(this.id, '-ms-transform', false);
+ }
+
+ OutputManager.updateProperty(this.id, 'transform', cssvalue);
+ OutputManager.updateProperty(this.id, '-webkit-transform', cssvalue);
+ OutputManager.updateProperty(this.id, '-ms-transform', cssvalue);
+ this.rotate = value;
+ }
+
+ CssClass.prototype.setzIndex = function setzIndex(value) {
+ this.node.style.zIndex = value;
+ OutputManager.updateProperty(this.id, 'z-index', value);
+ this.zIndex = value;
+ }
+
+ CssClass.prototype.toggleDisplay = function toggleDisplay(value) {
+ if (typeof value !== "boolean" || this.display === value)
+ return;
+
+ this.display = value;
+ var display = this.display === true ? "block" : "none";
+ this.node.style.display = display;
+ this.object.style.display = display;
+ }
+
+ CssClass.prototype.toggleBorder = function toggleBorder(value) {
+ if (typeof value !== "boolean" || this.border === value)
+ return;
+
+ this.border = value;
+ var border = this.border === true ? "1px solid #CCC" : "none";
+ this.node.style.border = border;
+ }
+
+ CssClass.prototype.updateBgColor = function updateBgColor(color) {
+ this.bgcolor.copy(color);
+ this.node.style.backgroundColor = color.getColor();
+ OutputManager.updateProperty(this.id, 'background-color', color.getColor());
+ }
+
+ CssClass.prototype.updateShadows = function updateShadows() {
+ if (this.render.length === 0)
+ OutputManager.toggleProperty(this.id, 'box-shadow', false);
+ if (this.render.length === 1)
+ OutputManager.toggleProperty(this.id, 'box-shadow', true);
+
+ this.node.style.boxShadow = this.render.join(", ");
+ OutputManager.updateProperty(this.id, 'box-shadow', this.render.join(", \n"));
+
+ }
+
+
+ /**
+ * Tool Manager
+ */
+ var Tool = (function Tool() {
+
+ var preview;
+ var classes = [];
+ var active = null;
+ var animate = false;
+
+ /*
+ * Toll actions
+ */
+ var addCssClass = function addCssClass(id) {
+ classes[id] = new CssClass(id);
+ }
+
+ var setActiveClass = function setActiveClass(id) {
+ active = classes[id];
+ active.shadowID = null;
+ ColoPicker.setColor(classes[id].bgcolor);
+ SliderManager.setValue("top", active.top);
+ SliderManager.setValue("left", active.left);
+ SliderManager.setValue("rotate", active.rotate);
+ SliderManager.setValue("z-index", active.zIndex);
+ SliderManager.setValue("width", active.width);
+ SliderManager.setValue("height", active.height);
+ ButtonManager.setValue("border-state", active.border);
+ active.updateShadows();
+ }
+
+ var disableClass = function disableClass(topic) {
+ classes[topic].toggleDisplay(false);
+ ButtonManager.setValue(topic, false);
+ }
+
+ var addShadow = function addShadow(position) {
+ if (animate === true)
+ return -1;
+
+ active.shadows.splice(position, 0, new Shadow());
+ active.render.splice(position, 0, null);
+ }
+
+ var swapShadow = function swapShadow(id1, id2) {
+ var x = active.shadows[id1];
+ active.shadows[id1] = active.shadows[id2];
+ active.shadows[id2] = x;
+ updateShadowCSS(id1);
+ updateShadowCSS(id2);
+ }
+
+ var deleteShadow = function deleteShadow(position) {
+ active.shadows.splice(position, 1);
+ active.render.splice(position, 1);
+ active.updateShadows();
+ }
+
+ var setActiveShadow = function setActiveShadow(id, glow) {
+ active.shadowID = id;
+ ColoPicker.setColor(active.shadows[id].color);
+ ButtonManager.setValue("inset", active.shadows[id].inset);
+ SliderManager.setValue("blur", active.shadows[id].blur);
+ SliderManager.setValue("spread", active.shadows[id].spread);
+ SliderManager.setValue("posX", active.shadows[id].posX);
+ SliderManager.setValue("posY", active.shadows[id].posY);
+ if (glow === true)
+ addGlowEffect(id);
+ }
+
+ var addGlowEffect = function addGlowEffect(id) {
+ if (animate === true)
+ return;
+
+ animate = true;
+ var store = new Shadow();
+ var shadow = active.shadows[id];
+
+ store.copy(shadow);
+ shadow.color.setRGBA(40, 125, 200, 1);
+ shadow.blur = 10;
+ shadow.spread = 10;
+
+ active.node.style.transition = "box-shadow 0.2s";
+ updateShadowCSS(id);
+
+ setTimeout(function() {
+ shadow.copy(store);
+ updateShadowCSS(id);
+ setTimeout(function() {
+ active.node.style.removeProperty("transition");
+ animate = false;
+ }, 100);
+ }, 200);
+ }
+
+ var updateActivePos = function updateActivePos(deltaX, deltaY) {
+ if (active.shadowID === null)
+ active.updatePos(deltaX, deltaY);
+ else
+ updateShadowPos(deltaX, deltaY);
+ }
+
+ /*
+ * Shadow properties
+ */
+ var updateShadowCSS = function updateShadowCSS(id) {
+ active.render[id] = active.shadows[id].computeCSS();
+ active.updateShadows();
+ }
+
+ var toggleShadowInset = function toggleShadowInset(value) {
+ if (active.shadowID === null)
+ return;
+ active.shadows[active.shadowID].toggleInset(value);
+ updateShadowCSS(active.shadowID);
+ }
+
+ var updateShadowPos = function updateShadowPos(deltaX, deltaY) {
+ var shadow = active.shadows[active.shadowID];
+ shadow.posX += deltaX;
+ shadow.posY += deltaY;
+ SliderManager.setValue("posX", shadow.posX);
+ SliderManager.setValue("posY", shadow.posY);
+ updateShadowCSS(active.shadowID);
+ }
+
+ var setShadowPosX = function setShadowPosX(value) {
+ if (active.shadowID === null)
+ return;
+ active.shadows[active.shadowID].posX = value;
+ updateShadowCSS(active.shadowID);
+ }
+
+ var setShadowPosY = function setShadowPosY(value) {
+ if (active.shadowID === null)
+ return;
+ active.shadows[active.shadowID].posY = value;
+ updateShadowCSS(active.shadowID);
+ }
+
+ var setShadowBlur = function setShadowBlur(value) {
+ if (active.shadowID === null)
+ return;
+ active.shadows[active.shadowID].blur = value;
+ updateShadowCSS(active.shadowID);
+ }
+
+ var setShadowSpread = function setShadowSpread(value) {
+ if (active.shadowID === null)
+ return;
+ active.shadows[active.shadowID].spread = value;
+ updateShadowCSS(active.shadowID);
+ }
+
+ var updateShadowColor = function updateShadowColor(color) {
+ active.shadows[active.shadowID].color.copy(color);
+ updateShadowCSS(active.shadowID);
+ }
+
+ /*
+ * Element Properties
+ */
+ var updateColor = function updateColor(color) {
+ if (active.shadowID === null)
+ active.updateBgColor(color);
+ else
+ updateShadowColor(color);
+ }
+
+ var init = function init() {
+ preview = getElemById("preview");
+
+ ColoPicker.subscribe("color", updateColor);
+ PreviewMouseTracking.subscribe(updateActivePos);
+
+ // Affects shadows
+ ButtonManager.subscribe("inset", toggleShadowInset);
+ SliderManager.subscribe("posX", setShadowPosX);
+ SliderManager.subscribe("posY", setShadowPosY);
+ SliderManager.subscribe("blur", setShadowBlur);
+ SliderManager.subscribe("spread", setShadowSpread);
+
+ // Affects element
+ SliderManager.subscribe("top", function(value){
+ active.setTop(value);
+ });
+ SliderManager.subscribe("left", function(value){
+ active.setLeft(value);
+ });
+ SliderManager.subscribe("rotate", function(value) {
+ if (active == classes["element"])
+ return;
+ active.setRotate(value);
+ });
+
+ SliderManager.subscribe("z-index", function(value) {
+ if (active == classes["element"])
+ return;
+ active.setzIndex(value);
+ });
+
+ SliderManager.subscribe("width", function(value) {
+ active.setWidth(value)
+ });
+
+ SliderManager.subscribe("height", function(value) {
+ active.setHeight(value)
+ });
+
+ // Actions
+ classes['before'].top = -30;
+ classes['before'].left = -30;
+ classes['after'].top = 30;
+ classes['after'].left = 30;
+ classes['before'].toggleDisplay(false);
+ classes['after'].toggleDisplay(false);
+ ButtonManager.setValue('before', false);
+ ButtonManager.setValue('after', false);
+
+ ButtonManager.subscribe("before", classes['before'].toggleDisplay.bind(classes['before']));
+ ButtonManager.subscribe("after", classes['after'].toggleDisplay.bind(classes['after']));
+
+ ButtonManager.subscribe("border-state", function(value) {
+ active.toggleBorder(value);
+ });
+
+ }
+
+ return {
+ init : init,
+ addShadow : addShadow,
+ swapShadow : swapShadow,
+ addCssClass : addCssClass,
+ disableClass : disableClass,
+ deleteShadow : deleteShadow,
+ setActiveClass : setActiveClass,
+ setActiveShadow : setActiveShadow
+ }
+
+ })();
+
+ /**
+ * Layer Manager
+ */
+ var LayerManager = (function LayerManager() {
+ var stacks = [];
+ var active = {
+ node : null,
+ stack : null
+ }
+ var elements = {};
+
+ var mouseEvents = function mouseEvents(e) {
+ var node = e.target;
+ var type = node.getAttribute('data-type');
+
+ if (type === 'subject')
+ setActiveStack(stacks[node.id]);
+
+ if (type === 'disable') {
+ Tool.disableClass(node.parentNode.id);
+ setActiveStack(stacks['element']);
+ }
+
+ if (type === 'add')
+ active.stack.addLayer();
+
+ if (type === 'layer')
+ active.stack.setActiveLayer(node);
+
+ if (type === 'delete')
+ active.stack.deleteLayer(node.parentNode);
+
+ if (type === 'move-up')
+ active.stack.moveLayer(1);
+
+ if (type === 'move-down')
+ active.stack.moveLayer(-1);
+ }
+
+ var setActiveStack = function setActiveStack(stackObj) {
+ active.stack.hide();
+ active.stack = stackObj;
+ active.stack.show();
+ }
+
+ /*
+ * Stack object
+ */
+ var Stack = function Stack(subject) {
+ var S = document.createElement('div');
+ var title = document.createElement('div');
+ var stack = document.createElement('div');
+
+ S.className = 'container';
+ stack.className = 'stack';
+ title.className = 'title';
+ title.textContent = subject.getAttribute('data-title');
+ S.appendChild(title);
+ S.appendChild(stack);
+
+ this.id = subject.id;
+ this.container = S;
+ this.stack = stack;
+ this.subject = subject;
+ this.order = [];
+ this.uid = 0;
+ this.count = 0;
+ this.layer = null;
+ this.layerID = 0;
+ }
+
+ Stack.prototype.addLayer = function addLayer() {
+ if (Tool.addShadow(this.layerID) == -1)
+ return;
+
+ var uid = this.getUID();
+ var layer = this.createLayer(uid);
+
+ if (this.layer === null &amp;&amp; this.stack.children.length &gt;= 1)
+ this.layer = this.stack.children[0];
+
+ this.stack.insertBefore(layer, this.layer);
+ this.order.splice(this.layerID, 0, uid);
+ this.count++;
+ this.setActiveLayer(layer);
+ }
+
+ Stack.prototype.createLayer = function createLayer(uid) {
+ var layer = document.createElement('div');
+ var del = document.createElement('span');
+
+ layer.className = 'node';
+ layer.setAttribute('data-shid', uid);
+ layer.setAttribute('data-type', 'layer');
+ layer.textContent = 'shadow ' + uid;
+
+ del.className = 'delete';
+ del.setAttribute('data-type', 'delete');
+
+ layer.appendChild(del);
+ return layer;
+ }
+
+ Stack.prototype.getUID = function getUID() {
+ return this.uid++;
+ }
+
+ // SOLVE IE BUG
+ Stack.prototype.moveLayer = function moveLayer(direction) {
+ if (this.count &lt;= 1 || this.layer === null)
+ return;
+ if (direction === -1 &amp;&amp; this.layerID === (this.count - 1) )
+ return;
+ if (direction === 1 &amp;&amp; this.layerID === 0 )
+ return;
+
+ if (direction === -1) {
+ var before = null;
+ Tool.swapShadow(this.layerID, this.layerID + 1);
+ this.swapOrder(this.layerID, this.layerID + 1);
+ this.layerID += 1;
+
+ if (this.layerID + 1 !== this.count)
+ before = this.stack.children[this.layerID + 1];
+
+ this.stack.insertBefore(this.layer, before);
+ Tool.setActiveShadow(this.layerID, false);
+ }
+
+ if (direction === 1) {
+ Tool.swapShadow(this.layerID, this.layerID - 1);
+ this.swapOrder(this.layerID, this.layerID - 1);
+ this.layerID -= 1;
+ this.stack.insertBefore(this.layer, this.stack.children[this.layerID]);
+ Tool.setActiveShadow(this.layerID, false);
+ }
+ }
+
+ Stack.prototype.swapOrder = function swapOrder(pos1, pos2) {
+ var x = this.order[pos1];
+ this.order[pos1] = this.order[pos2];
+ this.order[pos2] = x;
+ }
+
+ Stack.prototype.deleteLayer = function deleteLayer(node) {
+ var shadowID = node.getAttribute('data-shid') | 0;
+ var index = this.order.indexOf(shadowID);
+ this.stack.removeChild(this.stack.children[index]);
+ this.order.splice(index, 1);
+ this.count--;
+
+ Tool.deleteShadow(index);
+
+ if (index &gt; this.layerID)
+ return;
+
+ if (index == this.layerID) {
+ if (this.count &gt;= 1) {
+ this.layerID = 0;
+ this.setActiveLayer(this.stack.children[0], true);
+ }
+ else {
+ this.layer = null;
+ this.show();
+ }
+ }
+
+ if (index &lt; this.layerID) {
+ this.layerID--;
+ Tool.setActiveShadow(this.layerID, true);
+ }
+
+ }
+
+ Stack.prototype.setActiveLayer = function setActiveLayer(node) {
+ elements.shadow_properties.style.display = 'block';
+ elements.element_properties.style.display = 'none';
+
+ if (this.layer)
+ this.layer.removeAttribute('data-active');
+
+ this.layer = node;
+ this.layer.setAttribute('data-active', 'layer');
+
+ var shadowID = node.getAttribute('data-shid') | 0;
+ this.layerID = this.order.indexOf(shadowID);
+ Tool.setActiveShadow(this.layerID, true);
+ }
+
+ Stack.prototype.unsetActiveLayer = function unsetActiveLayer() {
+ if (this.layer)
+ this.layer.removeAttribute('data-active');
+
+ this.layer = null;
+ this.layerID = 0;
+ }
+
+ Stack.prototype.hide = function hide() {
+ this.unsetActiveLayer();
+ this.subject.removeAttribute('data-active');
+ var style = this.container.style;
+ style.left = '100%';
+ style.zIndex = '0';
+ }
+
+ Stack.prototype.show = function show() {
+ elements.shadow_properties.style.display = 'none';
+ elements.element_properties.style.display = 'block';
+
+ if (this.id === 'element') {
+ elements.zIndex.style.display = 'none';
+ elements.transform_rotate.style.display = 'none';
+ }
+ else {
+ elements.zIndex.style.display = 'block';
+ elements.transform_rotate.style.display = 'block';
+ }
+
+ this.subject.setAttribute('data-active', 'subject');
+ var style = this.container.style;
+ style.left = '0';
+ style.zIndex = '10';
+ Tool.setActiveClass(this.id);
+ }
+
+ function init() {
+
+ var elem, size;
+ var layerManager = getElemById("layer_manager");
+ var layerMenu = getElemById("layer_menu");
+ var container = getElemById("stack_container");
+
+ elements.shadow_properties = getElemById('shadow_properties');
+ elements.element_properties = getElemById('element_properties');
+ elements.transform_rotate = getElemById('transform_rotate');
+ elements.zIndex = getElemById('z-index');
+
+ elem = document.querySelectorAll('#layer_menu [data-type="subject"]');
+ size = elem.length;
+
+ for (var i = 0; i &lt; size; i++) {
+ var S = new Stack(elem[i]);
+ stacks[elem[i].id] = S;
+ container.appendChild(S.container);
+ Tool.addCssClass(elem[i].id);
+ }
+
+ active.stack = stacks['element'];
+ stacks['element'].show();
+
+ layerManager.addEventListener("click", mouseEvents);
+ layerMenu.addEventListener("click", mouseEvents);
+
+ ButtonManager.subscribe("before", function(value) {
+ if (value === false &amp;&amp; active.stack === stacks['before'])
+ setActiveStack(stacks['element'])
+ if (value === true &amp;&amp; active.stack !== stacks['before'])
+ setActiveStack(stacks['before'])
+ });
+
+ ButtonManager.subscribe("after", function(value) {
+ if (value === false &amp;&amp; active.stack === stacks['after'])
+ setActiveStack(stacks['element'])
+ if (value === true &amp;&amp; active.stack !== stacks['after'])
+ setActiveStack(stacks['after'])
+ });
+ }
+
+ return {
+ init : init
+ }
+ })();
+
+ /*
+ * OutputManager
+ */
+ var OutputManager = (function OutputManager() {
+ var classes = [];
+ var buttons = [];
+ var active = null;
+ var menu = null;
+ var button_offset = 0;
+
+ var crateOutputNode = function(topic, property) {
+
+ var prop = document.createElement('div');
+ var name = document.createElement('span');
+ var value = document.createElement('span');
+
+ var pmatch = property.match(/(^([a-z0-9\-]*)=\[([a-z0-9\-\"]*)\])|^([a-z0-9\-]*)/i);
+
+ name.textContent = '\t' + pmatch[4];
+
+ if (pmatch[3] !== undefined) {
+ name.textContent = '\t' + pmatch[2];
+ value.textContent = pmatch[3] + ';';
+ }
+
+ name.textContent += ': ';
+ prop.className = 'css-property';
+ name.className = 'name';
+ value.className = 'value';
+ prop.appendChild(name);
+ prop.appendChild(value);
+
+ classes[topic].node.appendChild(prop);
+ classes[topic].line[property] = prop;
+ classes[topic].prop[property] = value;
+ }
+
+ var OutputClass = function OutputClass(node) {
+ var topic = node.getAttribute('data-topic');
+ var prop = node.getAttribute('data-prop');
+ var name = node.getAttribute('data-name');
+ var properties = prop.split(' ');
+
+ classes[topic] = {};
+ classes[topic].node = node;
+ classes[topic].prop = [];
+ classes[topic].line = [];
+ classes[topic].button = new Button(topic);
+
+ var open_decl = document.createElement('div');
+ var end_decl = document.createElement('div');
+
+ open_decl.textContent = name + ' {';
+ end_decl.textContent = '}';
+ node.appendChild(open_decl);
+
+ for (var i in properties)
+ crateOutputNode(topic, properties[i]);
+
+ node.appendChild(end_decl);
+ }
+
+ var Button = function Button(topic) {
+ var button = document.createElement('div');
+
+ button.className = 'button';
+ button.textContent = topic;
+ button.style.left = button_offset + 'px';
+ button_offset += 100;
+
+ button.addEventListener("click", function() {
+ toggleDisplay(topic);
+ })
+
+ menu.appendChild(button);
+ return button;
+ }
+
+ var toggleDisplay = function toggleDisplay(topic) {
+ active.button.removeAttribute('data-active');
+ active.node.style.display = 'none';
+ active = classes[topic];
+ active.node.style.display = 'block';
+ active.button.setAttribute('data-active', 'true');
+ }
+
+ var toggleButton = function toggleButton(topic, value) {
+ var display = (value === true) ? 'block' : 'none';
+ classes[topic].button.style.display = display;
+
+ if (value === true)
+ toggleDisplay(topic);
+ else
+ toggleDisplay('element');
+ }
+
+ var updateProperty = function updateProperty(topic, property, data) {
+ try {
+ classes[topic].prop[property].textContent = data + ';';
+ }
+ catch(error) {
+ // console.log("ERROR undefined : ", topic, property, data);
+ }
+ }
+
+ var toggleProperty = function toggleProperty(topic, property, value) {
+ var display = (value === true) ? 'block' : 'none';
+ try {
+ classes[topic].line[property].style.display = display;
+ }
+ catch(error) {
+ // console.log("ERROR undefined : ",classes, topic, property, value);
+ }
+ }
+
+ var init = function init() {
+
+ menu = getElemById('menu');
+
+ var elem = document.querySelectorAll('#output .output');
+ var size = elem.length;
+ for (var i = 0; i &lt; size; i++)
+ OutputClass(elem[i]);
+
+ active = classes['element'];
+ toggleDisplay('element');
+
+ ButtonManager.subscribe("before", function(value) {
+ toggleButton('before', value);
+ });
+
+ ButtonManager.subscribe("after", function(value) {
+ toggleButton('after', value);
+ });
+ }
+
+ return {
+ init : init,
+ updateProperty : updateProperty,
+ toggleProperty : toggleProperty
+ }
+
+ })();
+
+
+ /**
+ * Init Tool
+ */
+ var init = function init() {
+ ButtonManager.init();
+ OutputManager.init();
+ ColoPicker.init();
+ SliderManager.init();
+ LayerManager.init();
+ PreviewMouseTracking.init("preview");
+ Tool.init();
+ }
+
+ return {
+ init : init
+ }
+
+})();
+
+
+</code></pre>
+</div>
+
+<div>{{ EmbedLiveSample('box-shadow_generator', '100%', '1100px', '') }}</div>
+
+<p><strong>Related Tool: </strong><a href="https://cssgenerator.org/box-shadow-css-generator.html">Box Shadow CSS Generator</a></p>
diff --git a/files/zh-cn/web/css/css_box_model/index.html b/files/zh-cn/web/css/css_box_model/index.html
new file mode 100644
index 0000000000..8d0de27817
--- /dev/null
+++ b/files/zh-cn/web/css/css_box_model/index.html
@@ -0,0 +1,112 @@
+---
+title: CSS 基础框盒模型
+slug: Web/CSS/CSS_Box_Model
+tags:
+ - CSS
+translation_of: Web/CSS/CSS_Box_Model
+---
+<p>{{CSSRef}}</p>
+
+<p><strong>CSS 基础框盒模型</strong>是 CSS 规范的一个模块,它定义了一种长方形的盒子——包括它们各自的内边距(padding)与外边距(margin ),并根据<a href="/zh-CN/docs/Web/CSS/Visual_formatting_model">视觉格式化模型</a>来生成元素,对其进行布置、编排、布局(lay out)。常被直译为盒子模型、盒模型或框模型。</p>
+
+<p>CSS 基础框盒模型一般仅针对单个元素及其边距、内容进行布局,而非对多个元素进行综合的排版,即使<a href="/zh-CN/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing">外边距合并</a>等特性涉及二个或二个以上元素之间部分属性的交互反馈。</p>
+
+<h2 id="参考">参考</h2>
+
+<h3 id="属性">属性</h3>
+
+<h4 id="控制框盒中内容流的属性">控制框盒中内容流的属性</h4>
+
+<div class="index">
+<ul>
+ <li>{{CSSxRef("overflow")}}</li>
+ <li>{{CSSxRef("overflow-x")}}</li>
+ <li>{{CSSxRef("overflow-y")}}</li>
+</ul>
+</div>
+
+<h4 id="控制框盒大小的属性">控制框盒大小的属性</h4>
+
+<div class="index">
+<ul>
+ <li>{{CSSxRef("height")}}</li>
+ <li>{{CSSxRef("width")}}</li>
+ <li>{{CSSxRef("max-height")}}</li>
+ <li>{{CSSxRef("max-width")}}</li>
+ <li>{{CSSxRef("min-height")}}</li>
+ <li>{{CSSxRef("min-width")}}</li>
+</ul>
+</div>
+
+<h4 id="控制外边距_Margin_的属性">控制外边距 Margin 的属性</h4>
+
+<div class="index">
+<ul>
+ <li>{{CSSxRef("margin")}}</li>
+ <li>{{CSSxRef("margin-bottom")}}</li>
+ <li>{{CSSxRef("margin-left")}}</li>
+ <li>{{CSSxRef("margin-right")}}</li>
+ <li>{{CSSxRef("margin-top")}}</li>
+ <li>{{CSSxRef("margin-trim")}} {{Experimental_Inline}}</li>
+</ul>
+</div>
+
+<h4 id="控制内边距_Padding_的属性">控制内边距 Padding 的属性</h4>
+
+<div class="index">
+<ul>
+ <li>{{CSSxRef("padding")}}</li>
+ <li>{{CSSxRef("padding-bottom")}}</li>
+ <li>{{CSSxRef("padding-left")}}</li>
+ <li>{{CSSxRef("padding-right")}}</li>
+ <li>{{CSSxRef("padding-top")}}</li>
+</ul>
+</div>
+
+<h4 id="其他属性">其他属性</h4>
+
+<div class="index">
+<ul>
+ <li>{{CSSxRef("visibility")}}</li>
+</ul>
+</div>
+
+<h2 id="指南">指南</h2>
+
+<dl>
+ <dt><a href="/zh-CN/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model">CSS 基础框盒模型介绍</a></dt>
+ <dd>解释了 CSS 的根本概念之一:框盒模型。该模型定义了 CSS 如何对元素的各个组成进行布局(lays out),这些组成包括他们的内容 Content、内边距 Padding、边框 Border,和外边距 Margin。</dd>
+ <dt><a href="/zh-CN/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing">掌握外边距合并</a></dt>
+ <dd>有时,两个相邻的外边距会折叠合并成一个。本文介绍了控制此特性的规则,比如合并何时发生、为何发生;以及应当如何控制它。</dd>
+ <dt><a href="/zh-CN/docs/Web/CSS/Visual_formatting_model">视觉格式化模型</a></dt>
+ <dd>解释了视觉格式化模型(visual formatting model)是什么,以及它的作用。</dd>
+</dl>
+
+<h2 id="规范">规范</h2>
+
+<table class="standard-table">
+ <thead>
+ <tr>
+ <th scope="col">规范</th>
+ <th scope="col">状态</th>
+ <th scope="col">备注</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>{{SpecName("CSS3 Box")}}</td>
+ <td>{{Spec2("CSS3 Box")}}</td>
+ <td>Added <code>margin-trim</code></td>
+ </tr>
+ <tr>
+ <td>{{SpecName("CSS2.1", "box.html")}}</td>
+ <td>{{Spec2("CSS2.1")}}</td>
+ <td> </td>
+ </tr>
+ <tr>
+ <td>{{SpecName("CSS1")}}</td>
+ <td>{{Spec2("CSS1")}}</td>
+ <td>Initial definition.</td>
+ </tr>
+ </tbody>
+</table>
diff --git a/files/zh-cn/web/css/css_box_model/introduction_to_the_css_box_model/index.html b/files/zh-cn/web/css/css_box_model/introduction_to_the_css_box_model/index.html
new file mode 100644
index 0000000000..90e9c23798
--- /dev/null
+++ b/files/zh-cn/web/css/css_box_model/introduction_to_the_css_box_model/index.html
@@ -0,0 +1,82 @@
+---
+title: CSS 基础框盒模型介绍
+slug: Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model
+tags:
+ - CSS Box Model
+ - 定位
+ - 布局
+ - 指南
+translation_of: Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model
+---
+<p>{{CSSRef}}</p>
+
+<div class="syntaxbox">
+<p>当对一个文档进行布局(lay out)的时候,浏览器的渲染引擎会根据标准之一的 <strong>CSS 基础框盒模型</strong>(<strong>CSS basic box model</strong>),将所有元素表示为一个个矩形的盒子(box)。CSS 决定这些盒子的大小、位置以及属性(例如颜色、背景、边框尺寸…)。</p>
+
+<p>每个盒子由四个部分(或称<em>区域</em>)组成,其效用由它们各自的边界(Edge)所定义(原文:defined by their respective edges,可能意指容纳、包含、限制等)。如图,与盒子的四个组成区域相对应,每个盒子有四个边界:<em>内容边界</em> <em>Content edge</em>、<em>内边距边界</em> <em>Padding Edge</em>、<em>边框边界</em> <em>Border Edge</em>、<em>外边框边界</em> <em>Margin Edge</em>。</p>
+
+<p><img alt="CSS Box model" src="https://mdn.mozillademos.org/files/8685/boxmodel-(3).png" style="height: 384px; width: 548px;"></p>
+
+<p><strong>内容区域 content area</strong> ,由内容边界限制,容纳着元素的“真实”内容,例如文本、图像,或是一个视频播放器。它的尺寸为内容宽度(或称 <em>content-box 宽度</em>)和内容高度(或称 <em>content-box 高度</em>)。它通常含有一个背景颜色(默认颜色为透明)或背景图像。</p>
+
+<p>如果 {{cssxref("box-sizing")}} 为 <code>content-box</code>(默认),则内容区域的大小可明确地通过 {{cssxref("width")}}、{{cssxref("min-width")}}、{{cssxref("max-width")}}、{{cssxref("height")}}、{{cssxref("min-height")}},和 {{cssxref("max-height")}} 控制。</p>
+
+<p><strong>内边距区域 padding area</strong> 由内边距边界限制,扩展自内容区域,负责延伸内容区域的背景,填充元素中内容与边框的间距。它的尺寸是 <em>padding-box 宽度</em> 和 <em>padding-box 高度</em>。</p>
+
+<p>内边距的粗细可以由 {{cssxref("padding-top")}}、{{cssxref("padding-right")}}、{{cssxref("padding-bottom")}}、{{cssxref("padding-left")}},和简写属性 {{cssxref("padding")}} 控制。</p>
+
+<p><strong>边框区域 border area</strong> 由边框边界限制,扩展自内边距区域,是容纳边框的区域。其尺寸为 <em>border-box  宽度</em> 和 <em>border-box 高度</em>。</p>
+
+<p>边框的粗细由 {{cssxref("border-width")}} 和简写的 {{cssxref("border")}} 属性控制。如果 {{cssxref("box-sizing")}} 属性被设为 <code>border-box</code>,那么边框区域的大小可明确地通过 {{cssxref("width")}}、{{cssxref("min-width")}}, {{cssxref("max-width")}}、{{ cssxref("height") }}、{{cssxref("min-height")}},和 {{cssxref("max-height")}} 属性控制。假如框盒上设有背景({{cssxref("background-color")}} 或 {{cssxref("background-image")}}),背景将会一直延伸至边框的外沿(默认为在边框下层延伸,边框会盖在背景上)。此默认表现可通过 CSS 属性 {{cssxref("background-clip")}} 来改变。</p>
+
+<p><strong>外边距区域 margin area</strong> 由外边距边界限制,用空白区域扩展边框区域,以分开相邻的元素。它的尺寸为 <em>margin-box 宽度 </em>和 <em>margin-box 高度</em>。</p>
+
+<p>外边距区域的大小由 {{cssxref("margin-top")}}、{{cssxref("margin-right")}}、{{cssxref("margin-bottom")}}、{{cssxref("margin-left")}},和简写属性 {{cssxref("margin")}} 控制。在发生<a href="/en/CSS/margin_collapsing" title="en/CSS/margin_collapsing">外边距合并</a>的情况下,由于盒之间共享外边距,外边距不容易弄清楚。</p>
+
+<p>最后,请注意,除<a href="/zh-CN/docs/Web/CSS/Replaced_element">可替换元素</a>外,对于行内元素来说,尽管内容周围存在内边距与边框,但其占用空间(每一行文字的高度)则由 {{cssxref('line-height')}} 属性决定,即使边框和内边距仍会显示在内容周围。</p>
+</div>
+
+<h2 id="参见">参见</h2>
+
+<ul>
+ <li><a href="/zh-CN/docs/Web/CSS/Containing_block">布局与包含块</a></li>
+ <li><a href="/zh-CN/docs/Web/CSS/Cascade">CSS 层叠介绍</a></li>
+ <li><a href="/zh-CN/docs/Learn/CSS/Introduction_to_CSS/Cascade_and_inheritance">层叠和继承</a></li>
+</ul>
+
+<h2 id="规范">规范</h2>
+
+<table class="standard-table">
+ <thead>
+ <tr>
+ <th scope="col">规范</th>
+ <th scope="col">状态</th>
+ <th scope="col">注释</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>{{SpecName('CSS3 Box', '#intro')}}</td>
+ <td>{{Spec2('CSS3 Box')}}</td>
+ <td> </td>
+ </tr>
+ <tr>
+ <td>{{ SpecName("CSS2.1","box.html#box-dimensions")}}</td>
+ <td>{{ Spec2('CSS2.1') }}</td>
+ <td>Though more precisely worded, there is no practical change.<br>
+ 尽管有了更详尽的描述,但没有实际上的变化。</td>
+ </tr>
+ <tr>
+ <td>{{SpecName("CSS1","#formatting-model")}}</td>
+ <td>{{Spec2('CSS1')}}</td>
+ <td>Initial definition.<br>
+ 最初的定义。</td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="参见_2">参见</h2>
+
+<ul>
+ <li>{{css_key_concepts}}</li>
+</ul>
diff --git a/files/zh-cn/web/css/css_box_model/mastering_margin_collapsing/index.html b/files/zh-cn/web/css/css_box_model/mastering_margin_collapsing/index.html
new file mode 100644
index 0000000000..d1b40704cf
--- /dev/null
+++ b/files/zh-cn/web/css/css_box_model/mastering_margin_collapsing/index.html
@@ -0,0 +1,151 @@
+---
+title: 外边距重叠
+slug: Web/CSS/CSS_Box_Model/Mastering_margin_collapsing
+tags:
+ - CSS
+ - CSS 盒模型
+ - 参考
+ - 指南
+translation_of: Web/CSS/CSS_Box_Model/Mastering_margin_collapsing
+---
+<div>{{CSSRef}}</div>
+
+<p>块的<a href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/margin-top">上外边距(margin-top)</a>和<a href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/margin-bottom">下外边距(margin-bottom)</a>有时合并(折叠)为单个边距,其大小为单个边距的最大值(或如果它们相等,则仅为其中一个),这种行为称为<strong>边距折叠</strong>。</p>
+
+<div class="blockIndicator note">
+<p>注意有设定<a href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/float">float</a>和<a href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/position#absolute">position=absolute</a>的元素不会产生外边距重叠行为。</p>
+</div>
+
+<div></div>
+
+<p>有三种情况会形成外边距重叠:</p>
+
+<dl>
+ <dt>同一层相邻元素之间</dt>
+ <dd>相邻的两个元素之间的外边距重叠,除非后一个元素加上<a href="/zh-CN/docs/Web/CSS/clear">clear-fix清除浮动</a>。</dd>
+</dl>
+
+<pre class="brush: html notranslate">&lt;style&gt;
+p:nth-child(1){
+ margin-bottom: 13px;
+}
+p:nth-child(2){
+ margin-top: 87px;
+}
+&lt;/style&gt;
+
+&lt;p&gt;下边界范围会...&lt;/p&gt;
+&lt;p&gt;...会跟这个元素的上边界范围重叠。&lt;/p&gt;</pre>
+
+<p>这个例子如果以为边界会合并的话,理所当然会猜测上下2个元素会合并一个100px的边界范围,但其实会发生边界折叠,只会挑选最大边界范围留下,所以这个例子的边界范围其实是87px。</p>
+
+<dl>
+ <dt>没有内容将父元素和后代元素分开</dt>
+ <dd>    如果没有边框{{cssxref("border")}},内边距{{cssxref("padding")}},行内内容,也没有创建<a href="https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Block_formatting_context">块级格式上下文</a>或<a href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/clear">清除浮动</a>来分开一个块级元素的上边界{{cssxref("margin-top")}} 与其内一个或多个后代块级元素的上边界{{cssxref("margin-top")}};或没有边框,内边距,行内内容,高度{{cssxref("height")}},最小高度{{cssxref("min-height")}}或 最大高度{{cssxref("max-height")}} 来分开一个块级元素的下边界{{cssxref("margin-bottom")}}与其内的一个或多个后代后代块元素的下边界{{cssxref("margin-bottom")}},则就会出现父块元素和其内后代块元素外边界重叠,重叠部分最终会溢出到父级块元素外面。</dd>
+</dl>
+
+<pre class="brush: html notranslate">&lt;style type="text/css"&gt;
+ section {
+ margin-top: 13px;
+ margin-bottom: 87px;
+ }
+
+ header {
+ margin-top: 87px;
+ }
+
+ footer {
+ margin-bottom: 13px;
+ }
+&lt;/style&gt;
+
+&lt;section&gt;
+ &lt;header&gt;上边界重叠 87&lt;/header&gt;
+  &lt;main&gt;&lt;/main&gt;
+ &lt;footer&gt;下边界重叠 87 不能再高了&lt;/footer&gt;
+&lt;/section&gt;</pre>
+
+<dl>
+ <dt>空的块级元素</dt>
+ <dd>当一个块元素上边界{{cssxref("margin-top")}} 直接贴到元素下边界{{cssxref("margin-bottom")}}时也会发生边界折叠。这种情况会发生在一个块元素完全没有设定边框{{cssxref("border")}}、内边距{{cssxref("paddng")}}、高度{{cssxref("height")}}、最小高度{{cssxref("min-height")}} 、最大高度{{cssxref("max-height")}} 、内容设定为inline或是加上<a href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/clear">clear-fix</a>的时候。</dd>
+</dl>
+
+<pre class="brush: html notranslate">&lt;style&gt;
+​​​​​​p {
+ margin: 0;
+}
+div {
+ margin-top: 13px;
+  margin-bottom: 87px;
+}
+&lt;/style&gt;
+
+&lt;p&gt;上边界范围是 87 ...&lt;/p&gt;
+&lt;div&gt;&lt;/div&gt;
+&lt;p&gt;... 上边界范围是 87&lt;/p&gt;</pre>
+
+<p>一些需要注意的地方:</p>
+
+<ul>
+ <li>上述情况的组合会产生更复杂的外边距折叠。</li>
+ <li>即使某一外边距为0,这些规则仍然适用。因此就算父元素的外边距是0,第一个或最后一个子元素的外边距仍然会“溢出”到父元素的外面。</li>
+ <li>如果参与折叠的外边距中包含负值,折叠后的外边距的值为最大的正边距与最小的负边距(即绝对值最大的负边距)的和,;也就是说如果有-13px 8px 100px叠在一起,边界范围的技术就是 100px -13px的87px。</li>
+ <li>如果所有参与折叠的外边距都为负,折叠后的外边距的值为最小的负边距的值。这一规则适用于相邻元素和嵌套元素。</li>
+</ul>
+
+<p>以上这些内容都是发生在Block-Level的元素,设定floating和absolutely positioned的元素完全不用担心边界重叠的问题。</p>
+
+<h2 id="示例">示例</h2>
+
+<h3 id="HTML">HTML</h3>
+
+<pre class="brush: html notranslate">&lt;p&gt;The bottom margin of this paragraph is collapsed …&lt;/p&gt;
+&lt;p&gt;… with the top margin of this paragraph, yielding a margin of &lt;code&gt;1.2rem&lt;/code&gt; in between.&lt;/p&gt;
+
+&lt;div&gt;This parent element contains two paragraphs!
+ &lt;p&gt;This paragraph has a &lt;code&gt;.4rem&lt;/code&gt; margin between it and the text above.&lt;/p&gt;
+ &lt;p&gt;My bottom margin collapses with my parent, yielding a bottom margin of &lt;code&gt;2rem&lt;/code&gt;.&lt;/p&gt;
+&lt;/div&gt;
+
+&lt;p&gt;I am &lt;code&gt;2rem&lt;/code&gt; below the element above.&lt;/p&gt;</pre>
+
+<h3 id="CSS">CSS</h3>
+
+<pre class="brush: css notranslate">div {
+ margin: 2rem 0;
+ background: lavender;
+}
+
+p {
+ margin: .4rem 0 1.2rem 0;
+ background: yellow;
+}</pre>
+
+<h3 id="结果">结果</h3>
+
+<p>{{EmbedLiveSample('示例', 'auto', 350)}}</p>
+
+<h2 id="规范">规范</h2>
+
+<table class="standard-table">
+ <thead>
+ <tr>
+ <th scope="col">Specification</th>
+ <th scope="col">Status</th>
+ <th scope="col">Comment</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>{{SpecName("CSS2.1", "box.html#collapsing-margins", "margin collapsing")}}</td>
+ <td>{{Spec2("CSS2.1")}}</td>
+ <td>初始定义</td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="参见">参见</h2>
+
+<ul>
+ <li>{{css_key_concepts}}</li>
+</ul>