├── .stylelintrc ├── tslint.json ├── img ├── bg.jpg ├── amazon.png ├── paypal.png ├── youtube.png ├── diggreader.png ├── grafikart.png ├── hackernews.png └── tvshowtime.png ├── .travis.yml ├── .gitignore ├── .babelrc ├── js ├── app.js ├── BubbleMouseListener.ts ├── BubbleHandler.ts └── bubble.ts ├── .editorconfig ├── .eslintrc ├── README.md ├── tsconfig.json ├── package.json ├── css └── app.scss ├── index.html └── .csscomb.json /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "stylelint-config-standard" 3 | } -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tslint-config-standard" 3 | } 4 | -------------------------------------------------------------------------------- /img/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Grafikart/Neon-Startpage/HEAD/img/bg.jpg -------------------------------------------------------------------------------- /img/amazon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Grafikart/Neon-Startpage/HEAD/img/amazon.png -------------------------------------------------------------------------------- /img/paypal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Grafikart/Neon-Startpage/HEAD/img/paypal.png -------------------------------------------------------------------------------- /img/youtube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Grafikart/Neon-Startpage/HEAD/img/youtube.png -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "6" 4 | - "7" 5 | script: npm run build 6 | -------------------------------------------------------------------------------- /img/diggreader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Grafikart/Neon-Startpage/HEAD/img/diggreader.png -------------------------------------------------------------------------------- /img/grafikart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Grafikart/Neon-Startpage/HEAD/img/grafikart.png -------------------------------------------------------------------------------- /img/hackernews.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Grafikart/Neon-Startpage/HEAD/img/hackernews.png -------------------------------------------------------------------------------- /img/tvshowtime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Grafikart/Neon-Startpage/HEAD/img/tvshowtime.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | dist 4 | public 5 | .idea 6 | npm-debug* 7 | *.iml 8 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "targets": { 5 | "browsers": ["last 2 versions", "safari >= 7"] 6 | } 7 | }] 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /js/app.js: -------------------------------------------------------------------------------- 1 | import { Bubble } from './bubble' 2 | 3 | let bubbles = document.querySelectorAll('.bubble') 4 | bubbles.forEach(function (bubble) { 5 | new Bubble(bubble) 6 | }) 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "babel-eslint", 4 | "parserOptions": { 5 | "sourceType": "module" 6 | }, 7 | "extends": "standard", 8 | "plugins": [ "html" ], 9 | "rules": { 10 | "arrow-parens": 0, 11 | "generator-star-spacing": 0, 12 | "no-debugger": 0, 13 | "no-new": 0 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Opera Neon Start Page 2 | 3 | This is a work in progress. The goal is to reproduce Opera Neon start page using HTML / CSS / JS 4 | 5 | Preview : https://grafikart.github.io/Neon-Startpage/dist/ 6 | 7 | ## TODO 8 | 9 | - Search bar 10 | - Better positioning of bubbles 11 | - Improve animations on hover using CSS instead of dynamics.js 12 | - Animate page opening (when clicking on a bubble) 13 | 14 | ## Future 15 | 16 | - Save bubble positions using localstorage 17 | - Create an interface to add bubbles 18 | 19 | ## Setup the project 20 | 21 | ```bash 22 | yarn 23 | npm run dev 24 | # npm run build 25 | ``` 26 | 27 | Then access to `localhost:3003` 28 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "es2015", 5 | "moduleResolution": "node", 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "allowSyntheticDefaultImports": true, 9 | "sourceMap": true, 10 | "noEmit": true, 11 | "noEmitHelpers": false, 12 | "strictNullChecks": false, 13 | "jsx": "preserve", 14 | "lib": [ 15 | "dom", 16 | "es2015", 17 | "es2015.promise" 18 | ], 19 | "types": [ 20 | ] 21 | }, 22 | "exclude": [ 23 | "node_modules", 24 | "dist", 25 | "src/**/*.spec.ts", 26 | "src/**/*.e2e.ts" 27 | ], 28 | "awesomeTypescriptLoaderOptions": { 29 | "forkChecker": true, 30 | "useWebpackText": true 31 | }, 32 | "compileOnSave": false, 33 | "buildOnSave": false, 34 | "atom": { 35 | "rewriteTsconfig": false 36 | } 37 | } -------------------------------------------------------------------------------- /js/BubbleMouseListener.ts: -------------------------------------------------------------------------------- 1 | import { BubbleHandlerOffsetInterface } from './BubbleHandler' 2 | 3 | export class BubbleMouseListener { 4 | 5 | private origin: BubbleHandlerOffsetInterface 6 | private movement: {x: number, y: number} 7 | private _canMove: boolean = false 8 | 9 | constructor(origin: BubbleHandlerOffsetInterface, e: MouseEvent) { 10 | this.origin = origin 11 | this.movement = { 12 | x: e.movementX, 13 | y: e.movementY 14 | } 15 | } 16 | 17 | /** 18 | * Un élément peut se déplacer si 19 | * - le curseur a dépasser la moitié de l'élément 20 | * - la souris change de sens 21 | * @param offset 22 | * @param e 23 | */ 24 | public canMove(offset: BubbleHandlerOffsetInterface, e: MouseEvent) { 25 | if (!this._canMove) { 26 | if (!this.sameSymbol(this.origin.x, offset.x) || !this.sameSymbol(this.origin.y, offset.y)) { 27 | this._canMove = true 28 | } else if (!this.sameSymbol(this.movement.x, e.movementX) || !this.sameSymbol(this.movement.y, e.movementY)) { 29 | this._canMove = true 30 | } 31 | } 32 | return this._canMove 33 | } 34 | 35 | private sameSymbol (x: number, y: number) { 36 | return (x >= 0 && y >= 0) || (x <= 0 && y <= 0) 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "grafikart-boilerplate", 3 | "version": "0.0.1", 4 | "description": "", 5 | "main": "", 6 | "scripts": { 7 | "updates": "npm-check-updates -u", 8 | "build": "NODE_ENV=production rimraf dist && webpack --config build/webpack.prod.js", 9 | "dev": "NODE_ENV=development node build/server.js", 10 | "gh": "npm run build && gh-pages -d dist" 11 | }, 12 | "author": "Grafikart ", 13 | "license": "MIT", 14 | "dependencies": { 15 | "dynamics.js": "^1.1.5" 16 | }, 17 | "devDependencies": { 18 | "assets-webpack-plugin": "^3.4.0", 19 | "autoprefixer": "^6.3.6", 20 | "awesome-typescript-loader": "3.0.0-beta.18", 21 | "babel-core": "^6.7.4", 22 | "babel-eslint": "^7.1.1", 23 | "babel-loader": "^6.2.4", 24 | "babel-preset-env": "^1.1.1", 25 | "chokidar": "^1.6.0", 26 | "css-loader": "^0.26.0", 27 | "css-mqpacker": "^5.0.1", 28 | "csswring": "^5.1.0", 29 | "eslint": "^3.5.0", 30 | "eslint-config-standard": "^6.0.0", 31 | "eslint-friendly-formatter": "^2.0.5", 32 | "eslint-loader": "^1.3.0", 33 | "eslint-plugin-html": "^1.5.2", 34 | "eslint-plugin-promise": "^3.4.0", 35 | "eslint-plugin-standard": "^2.0.0", 36 | "extract-text-webpack-plugin": "^2.0.0-beta.4", 37 | "file-loader": "^0.9.0", 38 | "html-webpack-plugin": "^2.22.0", 39 | "node-sass": "^4.0.0", 40 | "postcss": "^5.2.6", 41 | "postcss-loader": "^1.1.1", 42 | "postcss-merge-rules": "^2.0.10", 43 | "progress-bar-webpack-plugin": "^1.9.0", 44 | "rimraf": "^2.5.4", 45 | "sass-loader": "^4.0.2", 46 | "shelljs": "^0.7.0", 47 | "style-loader": "^0.13.1", 48 | "stylelint-config-standard": "^15.0.0", 49 | "stylelint-webpack-plugin": "^0.5.1", 50 | "tslint": "^4.3.1", 51 | "tslint-config-standard": "^2.0.0", 52 | "tslint-loader": "^3.3.0", 53 | "typescript": "^2.1.4", 54 | "url-loader": "^0.5.7", 55 | "webpack": "beta", 56 | "webpack-dev-server": "^2.1.0-beta.12", 57 | "webpack-hot-middleware": "^2.13.0" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /js/BubbleHandler.ts: -------------------------------------------------------------------------------- 1 | import dynamics from 'dynamics.js' 2 | 3 | export interface BubbleHandlerOffsetInterface { 4 | x: number, 5 | y: number 6 | } 7 | 8 | /** 9 | * Handle everything about the bubble (circle element with the data-handle attribute) 10 | */ 11 | export class BubbleHandler { 12 | 13 | public element: HTMLElement 14 | 15 | private center: {x: number, y: number} 16 | private width: number 17 | private height: number 18 | private expansion = 10 19 | private delta: number 20 | 21 | constructor (element: HTMLElement, delta) { 22 | this.element = element 23 | element.style.margin = `${this.expansion / 2}px` 24 | this.setPosition(element) 25 | this.delta = delta 26 | window.addEventListener('resize', () => { 27 | this.setPosition(element) 28 | }) 29 | } 30 | 31 | public setPosition (element: HTMLElement) { 32 | let rect = element.getBoundingClientRect() 33 | this.center = { 34 | x: rect.left + window.scrollX + rect.width / 2, 35 | y: rect.top + window.scrollY + rect.height / 2 36 | } 37 | this.width = rect.width 38 | this.height = rect.height 39 | } 40 | 41 | /** 42 | * Get mouse position relative to the center of the handle 43 | * @param e 44 | * @returns {{x: number, y: number}} 45 | */ 46 | public getOffset(e: MouseEvent) { 47 | return { 48 | x: (e.pageX - this.center.x) / ((this.width + this.delta) / 2), 49 | y: (e.pageY - this.center.y) / ((this.height + this.delta) / 2) 50 | } 51 | } 52 | 53 | /** 54 | * Shrink animation 55 | */ 56 | public shrink () { 57 | dynamics.animate( 58 | this.element, 59 | { 60 | width: this.width, 61 | height: this.height, 62 | margin: this.expansion / 2 63 | }, 64 | { 65 | duration: 600, 66 | type: dynamics.spring 67 | } 68 | ) 69 | } 70 | 71 | /** 72 | * Expand animation 73 | */ 74 | public expand () { 75 | dynamics.animate( 76 | this.element, 77 | { 78 | width: this.width + this.expansion, 79 | height: this.height + this.expansion, 80 | margin: 0 81 | }, 82 | { 83 | duration: 600, 84 | type: dynamics.spring 85 | } 86 | ) 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /css/app.scss: -------------------------------------------------------------------------------- 1 | body, 2 | html { 3 | width: 100%; 4 | height: 100%; 5 | margin: 0; 6 | padding: 0; 7 | background: center center no-repeat; 8 | background-size: cover; 9 | font-family: "Open Sans", sans-serif; 10 | overflow: hidden; 11 | } 12 | 13 | .overlay { 14 | position: absolute; 15 | top: 0; 16 | left: 0; 17 | bottom: 0; 18 | right: 0; 19 | width: 100%; 20 | height: 100%; 21 | background-color: rgba(#000, 0.5); 22 | } 23 | 24 | .bubbles { 25 | position: relative; 26 | } 27 | 28 | .bubble { 29 | position: absolute; 30 | text-align: center; 31 | top: 0; 32 | left: 0; 33 | margin-top: -50px; 34 | margin-left: -50px; 35 | color: #fff; 36 | text-decoration: none; 37 | } 38 | 39 | .bubble__image { 40 | position: relative; 41 | width: 100px; 42 | height: 100px; 43 | overflow: hidden; 44 | border-radius: 100px; 45 | background-position: center center; 46 | background-size: 120px 120px; 47 | } 48 | 49 | .bubble__image::after { 50 | content: ''; 51 | position: absolute; 52 | top: 0; 53 | left: 0; 54 | width: 100%; 55 | height: 100%; 56 | background-color: #fff; 57 | border-radius: 100px; 58 | opacity: 0; 59 | } 60 | 61 | .bubble__image:hover::after { 62 | // animation: blink 0.4s; 63 | } 64 | 65 | .bubble__label { 66 | padding-top: 5px; 67 | font-size: 14px; 68 | } 69 | 70 | @keyframes blink { 71 | 0% { opacity: 0; } 72 | 50% { opacity: 0.1; } 73 | 100% { opacity: 0; } 74 | } 75 | 76 | .container { 77 | width: 740px; 78 | margin: 0 auto; 79 | padding-top: 105px; 80 | } 81 | 82 | .form { 83 | position: relative; 84 | height: 47px; 85 | margin-bottom: 150px; 86 | 87 | input { 88 | display: block; 89 | width: 100%; 90 | border: none; 91 | font-size: 18px; 92 | color: #fff; 93 | outline: none; 94 | padding: 13px 0 13px 15px; 95 | background-color: transparent; 96 | } 97 | 98 | &::after { 99 | content: ''; 100 | position: absolute; 101 | bottom: 0; 102 | left: 0; 103 | right: 0; 104 | width: 100%; 105 | height: 1px; 106 | background-color: rgba(#fff, 0.4); 107 | animation: grow 0.5s; 108 | transform-origin: 100% 100%; 109 | } 110 | } 111 | 112 | @keyframes grow { 113 | 0% { transform: scaleX(0); } 114 | 100% { transform: scaleX(1); } 115 | } 116 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Bubbles ! 5 | 6 | 7 | 8 |
9 | 10 | 48 | 49 |
50 | 51 | 52 | -------------------------------------------------------------------------------- /js/bubble.ts: -------------------------------------------------------------------------------- 1 | import dynamics from 'dynamics.js' 2 | import { BubbleHandler, BubbleHandlerOffsetInterface } from './BubbleHandler' 3 | import { BubbleMouseListener} from './BubbleMouseListener' 4 | 5 | /** 6 | * Make a bubble "move" on mousehover 7 | */ 8 | export class Bubble { 9 | 10 | private element: HTMLElement 11 | private delta = 15 12 | private handle: BubbleHandler 13 | private listener: BubbleMouseListener 14 | 15 | constructor(element: HTMLElement) { 16 | this.element = element 17 | this.setPosition(element) 18 | this.handle = new BubbleHandler(element.querySelector('[data-handle]') as HTMLElement, this.delta) 19 | this.handle.element.addEventListener('mousemove', (e) => { 20 | window.requestAnimationFrame(() => this.mouseMove(e) ) 21 | }) 22 | this.handle.element.addEventListener('mouseover', this.mouseOver.bind(this)) 23 | this.handle.element.addEventListener('mouseout', this.mouseOut.bind(this)) 24 | this.animateEnter(this.element) 25 | } 26 | 27 | private setPosition (element: HTMLElement) { 28 | const index = Array.from((element.parentNode as HTMLElement).children).indexOf(element) + 1 29 | const row = Math.ceil(index / 5) - 1 30 | const position = index - row * 5 // position from 1 to 5 31 | const randomX = Math.random() * 20 - 10 32 | const randomY = Math.random() * 80 - 50 33 | const rowHeight = 150 34 | if (position < 3) { 35 | element.style.top = (rowHeight * 2 * row + randomY) + 'px' 36 | element.style.left = (33.33 * position + randomX) + '%' 37 | } else { 38 | element.style.top = (rowHeight + rowHeight * 2 * row + randomY) + 'px' 39 | switch (position - 3) { 40 | case 0: 41 | element.style.left = (10 + randomX) + '%' 42 | break 43 | case 1: 44 | element.style.left = (50 + randomX) + '%' 45 | break 46 | default: 47 | element.style.left = (90 + randomX) + '%' 48 | break 49 | } 50 | } 51 | } 52 | 53 | /** 54 | * Entry animation for bubbles 55 | */ 56 | private animateEnter(element) { 57 | dynamics.css( 58 | this.element, 59 | { 60 | translateY: window.innerHeight 61 | } 62 | ) 63 | dynamics.animate( 64 | this.element, 65 | { 66 | translateY: 0 67 | }, 68 | { 69 | duration: 1200, 70 | type: dynamics.spring, 71 | delay: 200 + Math.random() * 200, 72 | frequency: 197, 73 | friction: 222 74 | } 75 | ) 76 | } 77 | 78 | private mouseOver (e: MouseEvent) { 79 | let offset = this.handle.getOffset(e) 80 | this.listener = new BubbleMouseListener(offset, e) 81 | this.handle.expand() 82 | } 83 | 84 | private mouseOut (e: MouseEvent) { 85 | this.handle.shrink() 86 | dynamics.animate( 87 | this.element, 88 | { 89 | translateX: 0, 90 | translateY: 0 91 | }, 92 | { 93 | duration: 600, 94 | type: dynamics.spring 95 | } 96 | ) 97 | } 98 | 99 | private mouseMove (e: MouseEvent) { 100 | let offset = this.handle.getOffset(e) 101 | if (this.listener.canMove(offset, e)) { 102 | let x: number = offset.x * this.delta 103 | let y: number = offset.y * this.delta 104 | this.element.style.transform = `translate3D(${x}px, ${y}px, 0)` 105 | } 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /.csscomb.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "always-semicolon": true, 4 | "block-indent": 2, 5 | "color-case": "lower", 6 | "color-shorthand": true, 7 | "element-case": "lower", 8 | "eof-newline": true, 9 | "leading-zero": false, 10 | "remove-empty-rulesets": true, 11 | "space-after-colon": 1, 12 | "space-after-combinator": 1, 13 | "space-before-selector-delimiter": 0, 14 | "space-between-declarations": "\n", 15 | "space-after-opening-brace": "\n", 16 | "space-before-closing-brace": "\n", 17 | "space-before-colon": 0, 18 | "space-before-combinator": 1, 19 | "space-before-opening-brace": 1, 20 | "strip-spaces": true, 21 | "unitless-zero": true, 22 | "vendor-prefix-align": true, 23 | "sort-order": [ 24 | [ 25 | "position", 26 | "top", 27 | "right", 28 | "bottom", 29 | "left", 30 | "z-index", 31 | "display", 32 | "float", 33 | "width", 34 | "min-width", 35 | "max-width", 36 | "height", 37 | "min-height", 38 | "max-height", 39 | "-webkit-box-sizing", 40 | "-moz-box-sizing", 41 | "box-sizing", 42 | "-webkit-appearance", 43 | "padding", 44 | "padding-top", 45 | "padding-right", 46 | "padding-bottom", 47 | "padding-left", 48 | "margin", 49 | "margin-top", 50 | "margin-right", 51 | "margin-bottom", 52 | "margin-left", 53 | "overflow", 54 | "overflow-x", 55 | "overflow-y", 56 | "-webkit-overflow-scrolling", 57 | "-ms-overflow-x", 58 | "-ms-overflow-y", 59 | "-ms-overflow-style", 60 | "clip", 61 | "clear", 62 | "font", 63 | "font-family", 64 | "font-size", 65 | "font-style", 66 | "font-weight", 67 | "font-variant", 68 | "font-size-adjust", 69 | "font-stretch", 70 | "font-effect", 71 | "font-emphasize", 72 | "font-emphasize-position", 73 | "font-emphasize-style", 74 | "font-smooth", 75 | "-webkit-hyphens", 76 | "-moz-hyphens", 77 | "hyphens", 78 | "line-height", 79 | "color", 80 | "text-align", 81 | "-webkit-text-align-last", 82 | "-moz-text-align-last", 83 | "-ms-text-align-last", 84 | "text-align-last", 85 | "text-emphasis", 86 | "text-emphasis-color", 87 | "text-emphasis-style", 88 | "text-emphasis-position", 89 | "text-decoration", 90 | "text-indent", 91 | "text-justify", 92 | "text-outline", 93 | "-ms-text-overflow", 94 | "text-overflow", 95 | "text-overflow-ellipsis", 96 | "text-overflow-mode", 97 | "text-shadow", 98 | "text-transform", 99 | "text-wrap", 100 | "-webkit-text-size-adjust", 101 | "-ms-text-size-adjust", 102 | "letter-spacing", 103 | "-ms-word-break", 104 | "word-break", 105 | "word-spacing", 106 | "-ms-word-wrap", 107 | "word-wrap", 108 | "-moz-tab-size", 109 | "-o-tab-size", 110 | "tab-size", 111 | "white-space", 112 | "vertical-align", 113 | "list-style", 114 | "list-style-position", 115 | "list-style-type", 116 | "list-style-image", 117 | "pointer-events", 118 | "-ms-touch-action", 119 | "touch-action", 120 | "cursor", 121 | "visibility", 122 | "zoom", 123 | "flex-direction", 124 | "flex-order", 125 | "flex-pack", 126 | "flex-align", 127 | "table-layout", 128 | "empty-cells", 129 | "caption-side", 130 | "border-spacing", 131 | "border-collapse", 132 | "content", 133 | "quotes", 134 | "counter-reset", 135 | "counter-increment", 136 | "resize", 137 | "-webkit-user-select", 138 | "-moz-user-select", 139 | "-ms-user-select", 140 | "-o-user-select", 141 | "user-select", 142 | "nav-index", 143 | "nav-up", 144 | "nav-right", 145 | "nav-down", 146 | "nav-left", 147 | "background", 148 | "background-color", 149 | "background-image", 150 | "-ms-filter:\\'progid:DXImageTransform.Microsoft.gradient", 151 | "filter:progid:DXImageTransform.Microsoft.gradient", 152 | "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader", 153 | "filter", 154 | "background-repeat", 155 | "background-attachment", 156 | "background-position", 157 | "background-position-x", 158 | "background-position-y", 159 | "-webkit-background-clip", 160 | "-moz-background-clip", 161 | "background-clip", 162 | "background-origin", 163 | "-webkit-background-size", 164 | "-moz-background-size", 165 | "-o-background-size", 166 | "background-size", 167 | "border", 168 | "border-color", 169 | "border-style", 170 | "border-width", 171 | "border-top", 172 | "border-top-color", 173 | "border-top-style", 174 | "border-top-width", 175 | "border-right", 176 | "border-right-color", 177 | "border-right-style", 178 | "border-right-width", 179 | "border-bottom", 180 | "border-bottom-color", 181 | "border-bottom-style", 182 | "border-bottom-width", 183 | "border-left", 184 | "border-left-color", 185 | "border-left-style", 186 | "border-left-width", 187 | "border-radius", 188 | "border-top-left-radius", 189 | "border-top-right-radius", 190 | "border-bottom-right-radius", 191 | "border-bottom-left-radius", 192 | "-webkit-border-image", 193 | "-moz-border-image", 194 | "-o-border-image", 195 | "border-image", 196 | "-webkit-border-image-source", 197 | "-moz-border-image-source", 198 | "-o-border-image-source", 199 | "border-image-source", 200 | "-webkit-border-image-slice", 201 | "-moz-border-image-slice", 202 | "-o-border-image-slice", 203 | "border-image-slice", 204 | "-webkit-border-image-width", 205 | "-moz-border-image-width", 206 | "-o-border-image-width", 207 | "border-image-width", 208 | "-webkit-border-image-outset", 209 | "-moz-border-image-outset", 210 | "-o-border-image-outset", 211 | "border-image-outset", 212 | "-webkit-border-image-repeat", 213 | "-moz-border-image-repeat", 214 | "-o-border-image-repeat", 215 | "border-image-repeat", 216 | "outline", 217 | "outline-width", 218 | "outline-style", 219 | "outline-color", 220 | "outline-offset", 221 | "-webkit-box-shadow", 222 | "-moz-box-shadow", 223 | "box-shadow", 224 | "filter:progid:DXImageTransform.Microsoft.Alpha(Opacity", 225 | "-ms-filter:\\'progid:DXImageTransform.Microsoft.Alpha", 226 | "opacity", 227 | "-ms-interpolation-mode", 228 | "-webkit-transition", 229 | "-moz-transition", 230 | "-ms-transition", 231 | "-o-transition", 232 | "transition", 233 | "-webkit-transition-delay", 234 | "-moz-transition-delay", 235 | "-ms-transition-delay", 236 | "-o-transition-delay", 237 | "transition-delay", 238 | "-webkit-transition-timing-function", 239 | "-moz-transition-timing-function", 240 | "-ms-transition-timing-function", 241 | "-o-transition-timing-function", 242 | "transition-timing-function", 243 | "-webkit-transition-duration", 244 | "-moz-transition-duration", 245 | "-ms-transition-duration", 246 | "-o-transition-duration", 247 | "transition-duration", 248 | "-webkit-transition-property", 249 | "-moz-transition-property", 250 | "-ms-transition-property", 251 | "-o-transition-property", 252 | "transition-property", 253 | "-webkit-transform", 254 | "-moz-transform", 255 | "-ms-transform", 256 | "-o-transform", 257 | "transform", 258 | "-webkit-transform-origin", 259 | "-moz-transform-origin", 260 | "-ms-transform-origin", 261 | "-o-transform-origin", 262 | "transform-origin", 263 | "-webkit-animation", 264 | "-moz-animation", 265 | "-ms-animation", 266 | "-o-animation", 267 | "animation", 268 | "-webkit-animation-name", 269 | "-moz-animation-name", 270 | "-ms-animation-name", 271 | "-o-animation-name", 272 | "animation-name", 273 | "-webkit-animation-duration", 274 | "-moz-animation-duration", 275 | "-ms-animation-duration", 276 | "-o-animation-duration", 277 | "animation-duration", 278 | "-webkit-animation-play-state", 279 | "-moz-animation-play-state", 280 | "-ms-animation-play-state", 281 | "-o-animation-play-state", 282 | "animation-play-state", 283 | "-webkit-animation-timing-function", 284 | "-moz-animation-timing-function", 285 | "-ms-animation-timing-function", 286 | "-o-animation-timing-function", 287 | "animation-timing-function", 288 | "-webkit-animation-delay", 289 | "-moz-animation-delay", 290 | "-ms-animation-delay", 291 | "-o-animation-delay", 292 | "animation-delay", 293 | "-webkit-animation-iteration-count", 294 | "-moz-animation-iteration-count", 295 | "-ms-animation-iteration-count", 296 | "-o-animation-iteration-count", 297 | "animation-iteration-count", 298 | "-webkit-animation-direction", 299 | "-moz-animation-direction", 300 | "-ms-animation-direction", 301 | "-o-animation-direction", 302 | "animation-direction" 303 | ] 304 | ] 305 | } 306 | --------------------------------------------------------------------------------