Effective前端6:避免页面卡顿

.aligncenter { clear: both; display: block; margin-left: auto; margin-right: auto }
.crayon-line span::after { content: " " }
p { font-size: 15px; text-indent: 2em }
#colorbox.crayon-colorbox,#cboxOverlay.crayon-colorbox,.crayon-colorbox #cboxWrapper { position: absolute; top: 0; left: 0; z-index: 9999; overflow: hidden }
#cboxOverlay.crayon-colorbox { position: fixed; width: 100%; height: 100% }
.crayon-colorbox #cboxMiddleLeft,.crayon-colorbox #cboxBottomLeft { clear: left }
.crayon-colorbox #cboxContent { position: relative }
.crayon-colorbox #cboxLoadedContent { overflow: auto }
.crayon-colorbox #cboxTitle { display: none !important }
.crayon-colorbox #cboxLoadingOverlay,.crayon-colorbox #cboxLoadingGraphic { position: absolute; top: 0; left: 0; width: 100%; height: 100% }
.crayon-colorbox #cboxPrevious,.crayon-colorbox #cboxNext,.crayon-colorbox #cboxClose,.crayon-colorbox #cboxSlideshow { cursor: pointer }
.crayon-colorbox .cboxPhoto { float: left; margin: auto; border: 0; display: block; max-width: none }
.crayon-colorbox .cboxIframe { width: 100%; height: 100%; display: block; border: 0 }
#colorbox.crayon-colorbox,.crayon-colorbox #cboxContent,.crayon-colorbox #cboxLoadedContent { }
#cboxOverlay.crayon-colorbox { background: #000 }
#colorbox.crayon-colorbox { outline: 0 }
.crayon-colorbox #cboxContent { margin-top: 20px; background: #000 }
.crayon-colorbox .cboxIframe { background: #fff }
.crayon-colorbox #cboxError { padding: 50px; border: 1px solid #ccc }
.crayon-colorbox #cboxLoadedContent { border: 5px solid #000; background: #fff }
.crayon-colorbox #cboxTitle { position: absolute; top: -20px; left: 0; color: #ccc }
.crayon-colorbox #cboxCurrent { position: absolute; top: -20px; right: 0; color: #ccc }
.crayon-colorbox #cboxPrevious,.crayon-colorbox #cboxNext,.crayon-colorbox #cboxSlideshow,.crayon-colorbox #cboxClose { border: 0; padding: 0; margin: 0; overflow: visible; width: auto; background: 0 }
.crayon-colorbox #cboxPrevious:active,.crayon-colorbox #cboxNext:active,.crayon-colorbox #cboxSlideshow:active,.crayon-colorbox #cboxClose:active { outline: 0 }
.crayon-colorbox #cboxSlideshow { position: absolute; top: -20px; right: 90px; color: #fff }
.crayon-colorbox #cboxContent { margin-top: 0 }
.crayon-colorbox #cboxLoadedContent { border: 0 }
#crayon-main-wrap .form-table th { width: 100px }
#crayon-log { display: none; max-height: 200px; border-color: #dfdfdf; background-color: white; border-width: 1px; border-style: solid; margin: 1px; padding: 3px; overflow: auto; white-space: pre; margin-bottom: 5px }
.crayon-span,.crayon-span-5,.crayon-span-10,.crayon-span-50,.crayon-span-100,.crayon-span-110 { line-height: 24px; display: inline-block }
.crayon-span-5 { min-width: 5px }
.crayon-span-10 { min-width: 10px }
.crayon-span-50 { min-width: 50px }
.crayon-span-100 { min-width: 100px }
.crayon-span-110 { min-width: 117px }
.crayon-span-margin { margin-left: 5px }
#height_mode,#width_mode { min-width: 65px }
.crayon-error { color: #F00 }
.crayon-success { color: #00F }
.crayon-warning { color: #ff8000 }
.crayon-help { min-height: 30px; padding: 5px 10px }
.crayon-help .crayon-help-close,.crayon-help .crayon-help-close:active,.crayon-help .crayon-help-close:hover { text-decoration: none; float: right; color: #000 }
.crayon-help span,.crayon-help a { margin: 0; padding: 0; font-size: 12px }
#crayon-log-text { font: 11px/13px Monaco, "MonacoRegular", "Courier New", monospace }
#crayon-log-controls { float: left; margin-right: 5px }
.crayon-table { font-size: 12px; border: 1px solid #999; padding: 0; margin: 0; margin-top: 12px }
.crayon-table td { vertical-align: top; border-bottom: 1px solid #AAA; padding: 0 6px; margin: 0; background: #EEE }
.crayon-table-light td { background: #f8f8f8 }
.crayon-table-header td { font-weight: bold; background: #CCC }
.crayon-table-last td,.crayon-table tr:last-child td { border: 0 }
#lang-info div { padding: 5px 0 }
.crayon-table .not-parsed { color: #F00 }
.crayon-table .parsed-with-errors { color: #f90 }
.crayon-table .successfully-parsed { color: #77a000 }
#crayon-live-preview,#crayon-log-wrapper { padding: 0; width: 100%; float: left; clear: both }
#crayon-live-preview { float: none; padding: 0 }
#crayon-logo { text-align: center }
#crayon-info,#crayon-info td { border: 0; padding: 0 5px; margin: 0 }
.crayon-admin-button { display: inline-block; text-align: center }
#crayon-subsection-langs-info { margin-top: 5px }
#crayon-theme-editor-admin-buttons { display: inline }
#crayon-theme-editor-admin-buttons .crayon-admin-button { margin-left: 5px }
#crayon-theme-info { display: table; padding: 0; margin: 0; margin-top: 5px }
#crayon-theme-info>div { display: table-cell; vertical-align: middle }
#crayon-theme-info .content * { float: left }
#crayon-theme-info .field { font-weight: bold }
#crayon-theme-info .field,#crayon-theme-info .value { margin-left: 5px }
#crayon-theme-info .description.value { font-style: italic; color: #999 }
#crayon-theme-info .type { text-align: center; min-width: 120px; font-weight: bold; border-right: 1px solid #ccc; padding-right: 5px }
#crayon-theme-info .type.stock { color: #666 }
#crayon-theme-info .type.user { color: #5b9a00 }
#crayon-editor-table td { vertical-align: top }
.small-icon { width: 24px; height: 24px; display: inline-block; margin: 5px 5px 0 0 }
#twitter-icon { background: url("../images/twitter.png") }
#gmail-icon { background: url("../images/google.png") }
#docs-icon { background: url("../images/docs.png") }
#git-icon { background: url("../images/github.png") }
#wp-icon { background: url("../images/wordpress-blue.png") }
#donate-icon { background: url("../images/donate.png"); width: 75px }
#crayon-donate,#crayon-donate input { margin: 0; display: inline; padding: 0 }
#crayon-theme-editor-info a { text-decoration: none !important; font-style: italic !important; color: #666 !important }
#crayon-main-wrap .form-table .note { font-style: italic; color: #999 }
#crayon-change-code-text { width: 400px; height: 300px }
.crayon-syntax { overflow: hidden !important; position: relative !important; text-align: left; direction: ltr !important }
.crayon-syntax div { background: 0; border: 0; padding: 0; margin: 0; text-align: left }
.crayon-syntax.crayon-loading { visibility: hidden }
.crayon-syntax,.crayon-syntax .crayon-main,.crayon-syntax .crayon-toolbar,.crayon-syntax .crayon-info,.crayon-syntax .crayon-plain,.crayon-syntax .crayon-code { width: 100% }
.crayon-syntax .crayon-main,.crayon-syntax .crayon-plain { overflow: auto }
.crayon-syntax,.crayon-syntax .crayon-main,.crayon-syntax .crayon-plain,.crayon-syntax .crayon-table { padding: 0; margin: 0 }
.crayon-syntax-inline { margin: 0 2px; padding: 0 2px }
.crayon-syntax .crayon-table { border: none !important; background: none !important; padding: 0 !important; margin-top: 0 !important; margin-right: 0 !important; margin-bottom: 0 !important; width: auto !important; border-spacing: 0 !important; border-collapse: collapse !important; table-layout: auto !important }
.crayon-syntax .crayon-table td,.crayon-syntax .crayon-table tr { padding: 0 !important; border: none !important; background: 0; vertical-align: top !important; margin: 0 !important }
.crayon-syntax .crayon-invisible { display: none !important }
.crayon-plain-tag { margin-bottom: 12px }
.crayon-popup .crayon-plain { display: block !important; width: 100% !important; height: 100% !important; opacity: 100 !important; position: relative !important }
.crayon-popup-window { background: #fff }
.crayon-syntax .crayon-num { text-align: center; padding: 0 5px; margin: 0 }
.crayon-syntax .crayon-toolbar { position: relative; overflow: hidden; z-index: 4 }
.crayon-syntax .crayon-info { position: absolute; overflow: hidden; display: none; z-index: 3; padding: 0; min-height: 18px; line-height: 18px }
.crayon-syntax .crayon-info div { padding: 2px !important; text-align: center }
.crayon-syntax .crayon-toolbar span { padding: 0 4px !important }
.crayon-syntax .crayon-toolbar .crayon-button { display: inline; float: left !important; position: relative; width: 24px; background-repeat: no-repeat; line-height: 15px; border: 0; text-decoration: none }
.crayon-toolbar .crayon-button,.crayon-toolbar .crayon-button:hover,.crayon-toolbar .crayon-button.crayon-pressed:hover { background-position: 0 center }
.crayon-toolbar .crayon-button.crayon-pressed,.crayon-toolbar .crayon-button:active,.crayon-toolbar .crayon-button.crayon-pressed:active { background-position: -24px 0 }
.crayon-toolbar .crayon-button.crayon-popup-button .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-popup-button:hover .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-popup-button.crayon-pressed:hover .crayon-button-icon { background-position: 0 0 }
.crayon-toolbar .crayon-button.crayon-copy-button .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-copy-button:hover .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-copy-button.crayon-pressed:hover .crayon-button-icon { background-position: 0 -16px }
.crayon-toolbar .crayon-button.crayon-nums-button .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-nums-button:hover .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-nums-button.crayon-pressed:hover .crayon-button-icon { background-position: 0 -32px }
.crayon-toolbar .crayon-button.crayon-plain-button .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-plain-button:hover .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-plain-button.crayon-pressed:hover .crayon-button-icon { background-position: 0 -48px }
.crayon-toolbar .crayon-button.crayon-mixed-button .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-mixed-button:hover .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-mixed-button.crayon-pressed:hover .crayon-button-icon { background-position: 0 -64px }
.crayon-toolbar .crayon-button.crayon-minimize .crayon-button-icon { background-position: 0 -80px; background-color: transparent !important }
.crayon-toolbar .crayon-button.crayon-expand-button .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-expand-button:hover .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-expand-button.crayon-pressed:hover .crayon-button-icon { background-position: 0 -96px }
.crayon-toolbar .crayon-button.crayon-wrap-button .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-wrap-button:hover .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-wrap-button.crayon-pressed:hover .crayon-button-icon { background-position: 0 -112px }
.crayon-toolbar .crayon-button.crayon-popup-button.crayon-pressed .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-popup-button:active .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-popup-button.crayon-pressed:active .crayon-button-icon { background-position: -24px 0 }
.crayon-toolbar .crayon-button.crayon-copy-button.crayon-pressed .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-copy-button:active .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-copy-button.crayon-pressed:active .crayon-button-icon { background-position: -24px -16px }
.crayon-toolbar .crayon-button.crayon-nums-button.crayon-pressed .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-nums-button:active .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-nums-button.crayon-pressed:active .crayon-button-icon { background-position: -24px -32px }
.crayon-toolbar .crayon-button.crayon-plain-button.crayon-pressed .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-plain-button:active .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-plain-button.crayon-pressed:active .crayon-button-icon { background-position: -24px -48px }
.crayon-toolbar .crayon-button.crayon-mixed-button.crayon-pressed .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-mixed-button:active .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-mixed-button.crayon-pressed:active .crayon-button-icon { background-position: -24px -64px }
.crayon-toolbar .crayon-button.crayon-minimize .crayon-button-icon { background-position: -24px -80px; background-color: transparent !important }
.crayon-toolbar .crayon-button.crayon-expand-button.crayon-pressed .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-expand-button:active .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-expand-button.crayon-pressed:active .crayon-button-icon { background-position: -24px -96px }
.crayon-toolbar .crayon-button.crayon-wrap-button.crayon-pressed .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-wrap-button:active .crayon-button-icon,.crayon-toolbar .crayon-button.crayon-wrap-button.crayon-pressed:active .crayon-button-icon { background-position: -24px -112px }
.crayon-syntax .crayon-toolbar .crayon-language { padding-right: 8px !important }
.crayon-syntax .crayon-title,.crayon-syntax .crayon-language { float: left }
.crayon-main::-webkit-scrollbar,.crayon-plain::-webkit-scrollbar { height: 6px; overflow: visible; width: 6px; background: #EEE }
.crayon-main::-webkit-scrollbar-thumb,.crayon-plain::-webkit-scrollbar-thumb { background-color: #CCC; border: 1px solid #AAA; min-height: 8px; padding: 0; border-width: 1px }
.crayon-main::-webkit-scrollbar-button,.crayon-plain::-webkit-scrollbar-button { height: 0; width: 0; padding: 0 }
.crayon-main::-webkit-scrollbar-track,.crayon-plain::-webkit-scrollbar-track { border-width: 0 0 0 4px; border: 1px solid #BBB; border-right: 0; border-bottom: 0 }
.crayon-main::-webkit-scrollbar-corner,.crayon-plain::-webkit-scrollbar-corner { background: #EEE }
.crayon-main::-webkit-scrollbar-thumb:hover,.crayon-plain::-webkit-scrollbar-thumb:hover { background: #AAA; border: 1px solid #777 }
.crayon-syntax .crayon-pre,.crayon-syntax pre { color: #000; white-space: pre; margin: 0; padding: 0; overflow: visible; background: none !important; border: none !important }
.crayon-syntax .crayon-line { padding: 0 5px }
.crayon-syntax.crayon-wrapped .crayon-line { white-space: pre-wrap !important; height: auto }
.crayon-syntax-inline .crayon-pre,.crayon-syntax-inline pre { white-space: normal }
.crayon-syntax-inline-nowrap .crayon-pre,.crayon-syntax-inline-nowrap pre { white-space: pre }
.crayon-syntax { font-family: Monaco, "MonacoRegular", "Courier New", monospace; font-weight: 500 }
.crayon-syntax .crayon-toolbar *::selection,.crayon-syntax .crayon-nums *::selection { background: transparent }
.crayon-table .crayon-nums-content { white-space: nowrap }
.crayon-syntax .crayon-num,.crayon-syntax .crayon-pre .crayon-line,.crayon-syntax .crayon-toolbar *,.crayon-syntax .crayon-pre * { font-family: inherit; font-size: inherit !important; line-height: inherit !important; font-weight: inherit !important; height: inherit }
.crayon-syntax .crayon-toolbar .crayon-button .crayon-button-icon { background-image: url("../images/toolbar/buttons.png"); height: 16px !important; width: 100%; position: absolute; left: 0; top: 50%; margin-top: -8px }
.crayon-syntax .crayon-toolbar .crayon-tools { position: absolute; right: 0 }
.crayon-syntax.crayon-expanded { position: absolute !important; margin: 0 !important }
.crayon-syntax.crayon-expanded .crayon-main { overflow: hidden !important }
.crayon-placeholder { width: 100% !important }
.crayon-toolbar-visible .crayon-toolbar { position: relative !important; margin-top: 0 !important; display: block !important }
.crayon-syntax.crayon-expanded .crayon-toolbar .crayon-tools { position: relative; right: auto; float: left !important }
.crayon-syntax .crayon-plain-wrap { height: auto !important; padding: 0 !important; margin: 0 !important }
.crayon-syntax .crayon-plain { width: 100%; height: 100%; position: absolute; opacity: 0; padding: 0 5px; margin: 0; border: 0; white-space: pre; overflow: auto; color: #000; background: #FFF }
.crayon-wrapped .crayon-plain { white-space: pre-wrap }
.bbp-body .crayon-syntax { clear: none !important }
.crayon-minimized .crayon-toolbar { cursor: pointer }
.crayon-minimized .crayon-plain-wrap,.crayon-minimized .crayon-main,.crayon-minimized .crayon-toolbar .crayon-tools * { display: none !important }
.crayon-minimized .crayon-toolbar .crayon-tools .crayon-minimize { display: block !important }
.crayon-minimized .crayon-toolbar { position: relative !important }
.crayon-syntax.crayon-minimized .crayon-toolbar { border-bottom: none !important }
.crayon-te *,#crayon-te-bar-content { font-family: "Lucida Grande", Arial, sans-serif !important; font-size: 12px }
.crayon-te input[type="text"],.crayon-te textarea { background: #f9f9f9; border: 1px solid #CCC; padding: 2px 4px; border-width: 1px; border-style: solid }
.crayon-te #crayon-code { font-family: monospace !important }
#crayon-te-content,#crayon-te-table { width: 100%; height: auto !important }
#crayon-range,#crayon-mark { width: 100px }
#crayon-te-table th,#crayon-te-table td { vertical-align: top; text-align: left }
.rtl #crayon-te-table th,.rtl #crayon-te-table td { text-align: right }
#crayon-te-table .crayon-tr-center td,#crayon-te-table .crayon-tr-center th { vertical-align: middle }
#crayon-te-table .crayon-nowrap { white-space: nowrap }
#crayon-te-bar { position: absolute; top: 0; left: 0; width: 100% }
#crayon-te-bar-content { border: 1px solid #666; border-bottom: 0; height: 26px; line-height: 25px; padding: 0 8px; padding-right: 0; background-color: #222; color: #cfcfcf }
#crayon-te-bar-content a { line-height: 25px; padding: 5px 10px; color: #DDD; font-weight: bold; text-decoration: none !important }
#crayon-te-bar-content a:hover { color: #FFF }
.crayon-te-seperator { color: #666; margin: 0; padding: 0 }
#crayon-te-bar-block { height: 34px; width: 100% }
#crayon-te-title { float: left }
#crayon-te-controls { float: right }
#crayon-url-th { vertical-align: top !important; padding-top: 5px }
.crayon-te-heading { font-size: 14px; font-weight: bold }
#crayon-te-settings-info { text-align: center }
.crayon-te-section { font-weight: bold; padding: 0 10px }
#crayon-te-sub-section { margin-left: 10px }
#crayon-te-sub-section .crayon-te-section { font-weight: normal; padding: 0 }
#crayon-code { height: 200px; white-space: pre }
#crayon-code,#crayon-url { width: 555px !important }
.crayon-disabled { background: #EEE !important }
.qt_crayon_highlight { background-image: linear-gradient(bottom,#daf2ff,white) !important }
.qt_crayon_highlight:hover { background: #ddebf2 !important }
.crayon-tag-editor-button-wrapper { display: inline-block }
.mce_crayon_tinymce { padding: 0 !important; margin: 2px 3px !important }
.mce-i-crayon_tinymce,.mce_crayon_tinymce { background: url("../images/crayon_tinymce.png") 0 0 !important }
a.mce_crayon_tinymce { background-position: 2px 0 !important }
.wp_themeSkin .mceButtonEnabled:hover span.mce_crayon_tinymce,.wp_themeSkin .mceButtonActive span.mce_crayon_tinymce { background-position: -20px 0 }
.wp_themeSkin span.mce_crayon_tinymce { background: none !important }
#crayon-te-table { margin-top: 26px; padding: 10px; border-collapse: separate !important; border-spacing: 2px !important }
#crayon-te-table th { width: 100px }
#crayon-te-clear { color: #666; background-color: #f4f4f4; border: 1px solid #CCC; margin-left: 8px }
#crayon-title { width: 360px }
#TB_window.crayon-te-ajax { overflow: auto !important }
#TB_window.crayon-te-ajax,#TB_window.crayon-te-ajax #TB_ajaxContent,#TB_window.crayon-te-ajax #TB_title { width: 680px !important }
#TB_window.crayon-te-ajax #TB_ajaxContent { padding: 0 !important; margin: 0 !important; width: 100% !important; height: auto !important; margin-top: 28px !important }
#TB_window.crayon-te-ajax #TB_title { position: fixed !important }
#TB_window.crayon-te-ajax #TB_title .crayon-te-submit { margin-top: 3px !important; float: right !important }
#TB_window.crayon-te-ajax a { color: #2587e2; text-decoration: none }
#TB_window.crayon-te-ajax a:hover { color: #499ce9 }
.crayon-te-quote { background: #DDD; padding: 0 2px }
#crayon-te-submit-wrapper { display: none }
#crayon-te-clear { display: none; margin: 0; margin-top: 10px }
.crayon-syntax-pre { background: red; white-space: pre; overflow: auto; display: block }
.crayon-question { padding: 1px 4px !important; text-decoration: none !important; color: #83b3cb !important; height: 15px !important; width: 15px !important }
.crayon-question:hover { background: #83b3cb !important; color: white !important; height: 15px !important; width: 15px !important }
.crayon-setting-changed,.crayon-setting-selected { background: #fffaad !important }
.crayon-question:hover { color: white; background: #a6d6ef }
#crayon-te-warning { display: none }
.crayon-te-info { padding: 5px !important; margin: 2px 0 !important }
#crayon-te-submit { margin-bottom: 5px }
.crayon-theme-github { margin-bottom: 25px !important; border: 1px solid #dedede !important; background-color: #f8f8ff !important; font-size: 100% !important; line-height: 130% !important }
.crayon-theme-github .crayon-toolbar { border-bottom: 1px solid #dedede !important; background-color: #eee !important }
.crayon-theme-github .crayon-toolbar .crayon-language,.crayon-theme-github .crayon-toolbar .crayon-title { font-size: 80% !important; color: #666 !important }
.crayon-theme-github .crayon-table .crayon-nums { background-color: #eee !important }
.crayon-theme-github .crayon-table .crayon-nums-content { padding-top: 5px !important; padding-bottom: 3px !important }
.crayon-theme-github .crayon-table .crayon-num { min-width: 1.2em !important; border-right: 1px solid #dedede !important; text-align: right !important; color: #aaa !important }
.crayon-theme-github .crayon-pre { padding-top: 5px !important; padding-bottom: 3px !important }
.crayon-theme-github .crayon-marked-line { background: #fffee2 !important }
.crayon-theme-github .crayon-marked-num { color: #1561ac !important; background: #b3d3f4 !important; border-width: 1px !important; border-color: #5999d9 !important }
.crayon-theme-github .crayon-pre .crayon-c { color: #999 !important; font-style: italic !important }
.crayon-theme-github .crayon-pre .crayon-s { color: #d14 !important }
.crayon-theme-github .crayon-pre .crayon-p { color: #b85c00 !important }
.crayon-theme-github .crayon-pre .crayon-ta { color: #FF0000 !important }
.crayon-theme-github .crayon-pre .crayon-k { color: teal !important }
.crayon-theme-github .crayon-pre .crayon-st { color: #000 !important; font-weight: bold !important }
.crayon-theme-github .crayon-pre .crayon-r { color: #000 !important; font-weight: bold !important }
.crayon-theme-github .crayon-pre .crayon-t { color: #800080 !important; font-weight: bold !important }
.crayon-theme-github .crayon-pre .crayon-m { color: #800080 !important }
.crayon-theme-github .crayon-pre .crayon-i { color: #000 !important }
.crayon-theme-github .crayon-pre .crayon-e { color: teal !important }
.crayon-theme-github .crayon-pre .crayon-v { color: #002D7A !important }
.crayon-theme-github .crayon-pre .crayon-cn { color: #099 !important }
.crayon-theme-github .crayon-pre .crayon-o { color: #006fe0 !important }
.crayon-theme-github .crayon-pre .crayon-sy { color: #333 !important }
.crayon-theme-github .crayon-pre .crayon-n { color: #666 !important; font-style: italic }
.crayon-theme-github .crayon-pre .crayon-f { color: #999 !important }
.crayon-theme-github .crayon-pre .crayon-h { color: #006fe0 !important }
.crayon-syntax .crayon-pre,.crayon-syntax pre { white-space: initial }
img { margin-top: 10px; margin-bottom: 10px }
img { margin-top: 10px; margin-bottom: 10px }

什么是页面卡顿?如下:

当拖动页面或者滚动的时候页面一卡一卡的,看起来不连贯,我们就说页面卡了,这是一种非常不友好的体验,怎么衡量页面卡顿的情况呢?

1. 失帧和帧率FPS

如果你家里买了电视盒的话,在设置里面应该会有一个输出设置:

上面选中的60Hz就是帧率(frame per second),即一秒钟60帧,换句话说,一秒钟的动画是由60幅静态图片连在一起形成的。60fps是动画播放比较理想、比较基础的要求。当然如果你的显卡要是连这个都支持不了的话那就没办法了。windows系统有个刷新频率也是这个意思。

所以卡了,就是失帧了,或者掉帧了,1秒钟没有60个画面,看起来不连贯了。这可能是因为在渲染某些帧所花的时间比较长,导致停留在这些帧的时间较长,所以画面停顿了。

2. 渲染流程

60fps就要求1帧的时间为1s / 60 = 16.67ms。浏览器显示页面的时候,要处理js逻辑,还要做渲染,每个执行片段不能超过16.67ms。实际上,浏览器内核自身支撑体系运行也需要消耗一些时间,所以留给我们的时间差不多只有10ms。这10ms里面需要做一些什么事情?在Chrome的开发者文档Rendering Performance里面提到这个流程:

首先你用js做了些逻辑,还触发了样式变化,style把应用的样式规则计算好之后,把影响到的页面元素进行重新布局,叫做layout,再把它画到内存的一个画布里面,paint成了像素,最后把这个画布刷到屏幕上去,叫做composite,形成一帧。

这几项的任何一项如果执行时间太长了,就会导致渲染这一帧的时间太长,平均帧率就会掉。假设这一帧花了50ms,那么此时的帧率就为1s / 50ms = 20fps.

当然上面的过程并不一定每一步都会执行,例如:

  1. 你的js只是做一些运算,并没有增删DOM或改变CSS,那么后续几步就不会执行
  2. style只改了颜色等不需要重新layout的属性就不用执行layout这一步
  3. style改了transform属性,在blink和edge浏览器里面不需要layout和paint,如下面css trigger的说明:

发生掉帧的时候,我们可以使用的Chrome的devtools的timeline来观察这个过程。以最开始的例子做说明。

3. 掉帧分析

打开timeline的标签,勾上js profile和paint这两个选项,然后点击左边的记录按钮:

在页面拖动地图,出现卡顿的情况后,点击关闭记录按钮,就会生成这次操作的详细过程,先看最上面的overview图:

最上面一栏是帧率,顶点表示60fps,红色方格表示渲染时间比较长的帧,Chrome把这种情况叫做jank。可以看到上面有3个比较大的低谷,这并不是异常的失帧,这是Chrome检测到页面没有动了,idle空闲了,自动降低帧率。第二栏是CPU,黄色的为script,紫色的是CSS,蓝色是html,可以看到往往script占了比较高的CPU。关于timeline更详细的说明,可以查看chrome的文档

我们注意到在6s和8s中间CPU占用有一个比较大的峰值,并且失帧得比较厉害:

选中这段区域,进行放大查看:

可以看到有好几帧都超过了16.67ms,其中有一帧甚至达到了81.8ms,所以难怪卡得那么厉害。我们重点看一下这一帧里面发生了什么。

这一帧的FPS只有1s / 81.8ms = 12fps,点击第二个tab展开:

其中js的处理用掉了46.8ms(js里面还要更新dom),排第二的rendering花掉了22.9ms,这个rendering包括上面说的css计算和layout:

最后的Painting,时间还是比较少的,只花了2.5ms:

所以最长的开销是js脚本,并且很可能js里面做了很多dom操作或者改了很多css,导致Rendering的时间也很长。

由于在开始记录之前勾选了js profile的选项,所以可观察这些js执行的具体开销,包括调用的函数栈及每个函数的执行时间:

最上面那个函数是XHR Ready State Change触发的,也就是说这一整段代码都是在一个ajax的success回调函数里面执行的。再往下可以看到回调函数里面调用的最耗时的两个函数:

其一的showMapResut就花费了22.65ms,它又调了removeOldHouses和addNewHouses,这两个各自的时间约为11ms。

而另一个showResult的时间更多:

快40ms,它下面的doShowResut和resizeContainer最为耗时。

所以我们找到4个最为耗时的函数。那接下来怎么办呢?

上面已经提到,每一帧留给我们的时间只有10ms。所以可以考虑把上面那4个函数拆了,分别在4个连续的帧里面执行。这样应该会改善很多。

4. 拆分代码段

我们把代码拆成一个个单元,每个单元就是一个task任务,每一帧执行之前就去取一个task执行。并且控制每个task的执行时间都在10ms以内。这样就可以解决问题。js在渲染每一帧之前会去调requestAnimationFrame(传一个函数的参数给它去执行)。所以用这一个api,并把task传给它。我们建立一个任务队列,为此封装一个Task类:

JavaScript

function Task(){
this.tasks = [];
}
//添加一个任务
Task.prototype.addTask = function(task){
this.tasks.push(task);
};
//每次重绘前取一个task执行
Task.prototype.draw = function(){
var that = this;
window.requestAnimationFrame(function(){
var tasks = that.tasks;
if(tasks.length){
var task = tasks.shift();
task();
}
window.requestAnimationFrame(function(){that.draw.call(that)});
});
};

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

functionTask(){

this.tasks=[];

}

//添加一个任务

Task.prototype.addTask=function(task){

this.tasks.push(task);

};

//每次重绘前取一个task执行

Task.prototype.draw=function(){

varthat=this;

window.requestAnimationFrame(function(){

vartasks=that.tasks;

if(tasks.length){

vartask=tasks.shift();

task();

}

window.requestAnimationFrame(function(){that.draw.call(that)});

});

};

使用的时候先new一个Task,然后调draw函数初始化。有任务的时候调addTask插到队尾,执行任务的时候调shift取出队头元素。

上面的实现其实有一点问题,因为requestAnimationFrame是全局的,每次new一个Task,进行draw的时候,会把上一个传给它的task给覆盖掉。但是这个是可以从代码层面上解决的,这里不展开讨论。

然后再封装一个mapTask的单例,存放map页面的task:

JavaScript

var aTask = null;

var mapTask = {
get: function(){
if(!aTask){
aTask = new Task();
aTask.draw();
}
return aTask;
},
add: function(task){
mapTask.get().addTask(task);
}
};

1

2

3

4

5

6

7

8

9

10

11

12

13

14

varaTask=null;

varmapTask={

get:function(){

if(!aTask){

aTask=newTask();

aTask.draw();

}

returnaTask;

},

add:function(task){

mapTask.get().addTask(task);

}

};

需要插入一个任务的时候就调一下mapTask.add,把上面4个十分耗时的函数分别当作一个任务插进去,下面是原本的执行逻辑:

JavaScript

updateHouses: function(houses){
var remainMultipleMarkers = null;
var housesFilter = null;
housesFilter = filterData.filterHouse(houses);
remainMultipleMarkers = filterData.removeOldHouses(housesFilter.remainsHouses);
housesFilter.newHouses = housesFilter.newHouses.concat(remainMultipleMarkers);
filterData.addNewHouses(housesFilter.newHouses);
},

1

2

3

4

5

6

7

8

updateHouses:function(houses){

varremainMultipleMarkers=null;

varhousesFilter=null;

housesFilter=filterData.filterHouse(houses);

remainMultipleMarkers=filterData.removeOldHouses(housesFilter.remainsHouses);

housesFilter.newHouses=housesFilter.newHouses.concat(remainMultipleMarkers);

filterData.addNewHouses(housesFilter.newHouses);

},

现在把它改成两个task,并加到任务队列里面:

JavaScript

mapTask.add(function(){
housesFilter = filterData.filterHouse(houses);
remainMultipleMarkers = filterData.removeOldHouses(housesFilter.remainsHouses);
});
mapTask.add(function(){
housesFilter.newHouses = housesFilter.newHouses.concat(remainMultipleMarkers);
filterData.addNewHouses(housesFilter.newHouses);
});

1

2

3

4

5

6

7

8

mapTask.add(function(){

housesFilter=filterData.filterHouse(houses);

remainMultipleMarkers=filterData.removeOldHouses(housesFilter.remainsHouses);

});

mapTask.add(function(){

housesFilter.newHouses=housesFilter.newHouses.concat(remainMultipleMarkers);

filterData.addNewHouses(housesFilter.newHouses);

});

同样地,把另外两个也这样改一下。

然后再拖动地图,查看效果,会发现页面瞬间爽滑了好多:

当把页面拖快的时候还是会有一点卡顿,但是比之前已经好很多。这里还有优化的空间,例如后面两个函数的执行时间还是比较长,可以把这两个函数再继续拆分task。

看一下timeline:

可以看到4个task分别在4帧执行,并且Task3还有很大的优化空间。

除了拆分代码段的方法外,还有其它一些地方要注意:

5. 其它的优化方法

(1)尽量减少layout

获取scrollTop、clentWidth等维度属性时都会触发layout以获取实时的值,所以在for循环里面应该把这些值缓存一下。以下代码:

JavaScript

for(var i = 0; i < childs.length){
childs.style.width = node.offsetWidth + "px";
}

1

2

3

for(vari=0;i<childs.length;i++){

childs.style.width=node.offsetWidth+"px";

}

应该改成:

JavaScript

var width = node.offsetWidth;
for(var i = 0; i < childs.length){
childs.style.width = width + "px";
}

1

2

3

4

varwidth=node.offsetWidth;

for(vari=0;i<childs.length ;i++){

childs.style.width=width+"px";

}

当循环次数很多的时候,优化版的代码会明显提高性能。

获取一个元素的样式(getComputedStyle)时,也会触发layout

另外,能够使用transform满足要求的就别使用position/width/height做动画。

(2)简化DOM结构

当DOM结构越复杂时,需要重绘的元素也就越多。所以dom应该保持简单,特别是那些要做动画的,或者要监听scroll/mousemove事件的。另外使用flex比使用float在重绘方面会有优势,详见:《Avoid Large, Complex Layouts and Layout Thrashing

参考:

  1. 淘宝首页性能优化实践
  2. 如何评价页面的性能

扩展阅读:

  1. Effective前端1:能使用html/css解决的问题就不要使用JS
  2. Effective前端2:优化html标签
  3. Effective前端3:用CSS画一个三角形
  4. Effective前端4:尽可能地使用伪元素
  5. Effective前端5:减少前端代码耦合
时间: 2024-08-10 19:15:35

Effective前端6:避免页面卡顿的相关文章

iOS中解决页面卡顿小技巧(很常用)

1.为什么出现页面卡顿? 在开发中我们常常会遇到布局比较复杂的cell,在滑动的时候会导致界面不流畅,出现卡顿的现象,这是由于CPU计算和GPU渲染,之间未及时交换数据丢失帧导致的结果. 2.常见解决办法 1).UIImageView尽量设置为不透明 opque尽量设置为YES 当UIImageView的opque设置为YES的时候其alpha的属性就会无效,UIImageView的半透明取决于其图片半透明或者UIImageView本身的背景色合成的图层view是半透明的. 如果图片全部不是半透

记录一个关于 Document.on绑定事件后,导致页面卡顿的情况

假设当前页面的js文件中有如下函数: function A(){ function B(); } function B(){ $(document).on("click","#元素id",function(){ dosomething……; }); } 函数A是一个按钮上绑定的onclick函数处理: 那么每次点击按钮触发A函数之后,都会导致B函数的执行,进而 $("#元素id") 这个元素就会绑定一次点击事件. 如果多次触发A函数之后,导致 $

前端页面卡顿?或是DOM操作惹的祸,需优化代码

文档对象模型(DOM)是一个独立 于特定语言的应用程序接口.在浏览器中,DOM接口是以JavaScript语言实现的,通过JavaScript来操作浏览器页面中的元素,这使得 DOM成为了JavaScript中重要的组成部分.在富客户端网页应用中,界面上UI的更改都是通过DOM操作实现的,并不是通过传统的刷新页面实现 的.尽管DOM提供了丰富接口供外部调用,但DOM操作的代价很高,页面前端代码的性能瓶颈也大多集中在DOM操作上,所以前端性能优化的一个主要的关注 点就是DOM操作的优化.DOM操作

better-scroll 上拉加载,下拉刷新(解决移动端长页面卡顿)

一.Better Scroll 滚动原理 1.下图能直观的表示better-scroll的滚动原理 2.html设置 <div class="wrapper"> <ul class="content"> <li>...</li> <li>...</li> ... </ul> <!-- 这里可以放一些其它的 DOM,但不会影响滚动 --> </div> 3.js

腾讯面试题,js处理1千万条数据排序并且页面不卡顿

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" con

一次优化列表页卡顿的经历

写下这篇文章的日期是2016年4月初.当时来到公司,项目之前是外包出去的,代码乱糟糟的,需要重构掉, 摆在面前的问题不是重构项目,而是一些列表页的紧急的性能优化. 1.先优化item的层级 其实层级只要不是太深的话,比如5层,6层,对性能的差别在中等性能的机器上几乎看不出来的,但是想要做到 极致, 我就得死扣细节,原来代码是有4层的,其实有一点点接近可优化的范围了,我把原来的4层降到1层. 1层的话在item的话,在cpu进行计算测量的时候就速度很快了. 下面是我用DDMS去查看某台和我台的列表

想让安卓app不再卡顿?看这篇文章就够了

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由likunhuang发表于云+社区专栏 实现背景 应用的使用流畅度,是衡量用户体验的重要标准之一.Android 由于机型配置和系统的不同,项目复杂App场景丰富,代码多人参与迭代历史较久,代码可能会存在很多UI线程耗时的操作,实际测试时候也会偶尔发现某些业务场景发生卡顿的现象,用户也经常反馈和投诉App使用遇到卡顿.因此,我们越来越关注和提升用户体验的流畅度问题. 已有方案 在这之前,我们将反馈的常见卡顿场景,或测试过程中常见的

跳出小程序 video组件 卡顿、黑屏、全屏等坑

前些天,朋友遇到一个小程序的问题叫我帮忙看看,说是ios上video组件会有严重的黑屏现象,这就有意思了. 知道问题后,我就开始试一试,发现如果页面只有一个video组件的话,是没有什么问题的.但是但页面有多个video的时候,问题就有点严重了: 1.设置了播放方式为非自动播放,但是进到页面的是还是时不时有一两个会自动播放 2.卡,页面很卡 3.进入全屏的时候,视频方向是根据宽高自己适配,但是退出全屏的时候,会出现这种情况:刚刚视频是横屏播放,退出了页面也是横屏 4.退出全屏后,页面上除了刚刚那

vue项目--浏览器出现卡顿及崩溃的原因查找与解决方案

最近客户反应在操作页面的过程中出现了卡顿甚至交互多一点浏览器直接崩溃了.项目的技术是vue + svg 所以我一直在想是不是svg交互导致的,但是svg涉及的交互也不是很多,不至于产生崩溃状态呀!后来又怀疑是代码问题,于是对大家都知道的一些内存泄露的情况进行了排查: 没有全局变量 没有定时器 没有使用未销毁的全局事件和第三方库 v-if和v-show合理使用了,v-if和v-for合理使用了 没有使用watch ... 确保代码层面是没有问题的,但是打开任务管理器,内存的确在随着点击选择交互而飙