Free and Open source Web Builder Framework. Next generation tool for building templates without coding
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

223 lines
48 KiB

<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Use Custom CSS Parser | GrapesJS</title>
<meta name="generator" content="VuePress 1.9.10">
<link rel="icon" href="/docs/logo-icon.png">
<link rel="stylesheet" href="https://grapesjs.com/stylesheets/grapes.min.css?v0.21.10">
<script src="https://grapesjs.com/js/grapes.min.js?v0.21.10"></script>
<meta name="description" content="GrapesJS documentation">
<link rel="preload" href="/docs/assets/css/0.styles.c7ff573f.css" as="style"><link rel="preload" href="/docs/assets/js/app.7cba500a.js" as="script"><link rel="preload" href="/docs/assets/js/4.0070552e.js" as="script"><link rel="preload" href="/docs/assets/js/2.6fefd022.js" as="script"><link rel="preload" href="/docs/assets/js/1.d23e9fed.js" as="script"><link rel="preload" href="/docs/assets/js/78.a8d38215.js" as="script"><link rel="prefetch" href="/docs/assets/js/12.fcd6c1b3.js"><link rel="prefetch" href="/docs/assets/js/13.f8ba6288.js"><link rel="prefetch" href="/docs/assets/js/14.37d1e434.js"><link rel="prefetch" href="/docs/assets/js/15.6e77df13.js"><link rel="prefetch" href="/docs/assets/js/16.c5f433ca.js"><link rel="prefetch" href="/docs/assets/js/17.de56d7c2.js"><link rel="prefetch" href="/docs/assets/js/18.bf39ac98.js"><link rel="prefetch" href="/docs/assets/js/19.ca87c57f.js"><link rel="prefetch" href="/docs/assets/js/20.68039d84.js"><link rel="prefetch" href="/docs/assets/js/21.2b429912.js"><link rel="prefetch" href="/docs/assets/js/22.27b0a8c5.js"><link rel="prefetch" href="/docs/assets/js/23.a6d68e8d.js"><link rel="prefetch" href="/docs/assets/js/24.74960541.js"><link rel="prefetch" href="/docs/assets/js/25.ca71342f.js"><link rel="prefetch" href="/docs/assets/js/26.33a13a48.js"><link rel="prefetch" href="/docs/assets/js/27.54f6b393.js"><link rel="prefetch" href="/docs/assets/js/28.cf1f128d.js"><link rel="prefetch" href="/docs/assets/js/29.5888c207.js"><link rel="prefetch" href="/docs/assets/js/3.4e94790f.js"><link rel="prefetch" href="/docs/assets/js/30.bace5f23.js"><link rel="prefetch" href="/docs/assets/js/31.2b0fa15d.js"><link rel="prefetch" href="/docs/assets/js/32.fdf463ac.js"><link rel="prefetch" href="/docs/assets/js/33.a739af41.js"><link rel="prefetch" href="/docs/assets/js/34.27801365.js"><link rel="prefetch" href="/docs/assets/js/35.55be1c25.js"><link rel="prefetch" href="/docs/assets/js/36.78a4b7a9.js"><link rel="prefetch" href="/docs/assets/js/37.a1d1286c.js"><link rel="prefetch" href="/docs/assets/js/38.7f94984b.js"><link rel="prefetch" href="/docs/assets/js/39.bae8130f.js"><link rel="prefetch" href="/docs/assets/js/40.d641c435.js"><link rel="prefetch" href="/docs/assets/js/41.2f0da2d4.js"><link rel="prefetch" href="/docs/assets/js/42.a0743242.js"><link rel="prefetch" href="/docs/assets/js/43.8460a28b.js"><link rel="prefetch" href="/docs/assets/js/44.943c0253.js"><link rel="prefetch" href="/docs/assets/js/45.aafa45da.js"><link rel="prefetch" href="/docs/assets/js/46.ad246b82.js"><link rel="prefetch" href="/docs/assets/js/47.b412adfe.js"><link rel="prefetch" href="/docs/assets/js/48.af9cac86.js"><link rel="prefetch" href="/docs/assets/js/49.86ad40ac.js"><link rel="prefetch" href="/docs/assets/js/5.08dc74a9.js"><link rel="prefetch" href="/docs/assets/js/50.f7509701.js"><link rel="prefetch" href="/docs/assets/js/51.8c42f1c6.js"><link rel="prefetch" href="/docs/assets/js/52.82b56909.js"><link rel="prefetch" href="/docs/assets/js/53.5f6601a1.js"><link rel="prefetch" href="/docs/assets/js/54.e8a69f95.js"><link rel="prefetch" href="/docs/assets/js/55.22891dc5.js"><link rel="prefetch" href="/docs/assets/js/56.f7e9921e.js"><link rel="prefetch" href="/docs/assets/js/57.578f14f1.js"><link rel="prefetch" href="/docs/assets/js/58.64b9e09c.js"><link rel="prefetch" href="/docs/assets/js/59.135e8739.js"><link rel="prefetch" href="/docs/assets/js/6.3a6e1ed3.js"><link rel="prefetch" href="/docs/assets/js/60.c21dfd9f.js"><link rel="prefetch" href="/docs/assets/js/61.c49c5b1e.js"><link rel="prefetch" href="/docs/assets/js/62.ce5bed3d.js"><link rel="prefetch" href="/docs/assets/js/63.3ee6f39c.js"><link rel="prefetch" href="/docs/assets/js/64.b439d27f.js"><link rel="prefetch" href="/docs/assets/js/65.ee472a88.js"><link rel="prefetch" href="/docs/assets/js/66.becd0d7a.js"><link rel="prefetch" href="/docs/assets/js/67.166cf34e.js"><link rel="prefetch" href="/docs/assets/js/68.36615226.js"><link rel="prefetch" href="/docs/assets/js/69.9a5913c7.js"><link rel="prefetch" href="/docs/assets/js/7.b99a3113.js"><link rel="prefetch" href="/docs/assets/js/70.8663a867.js"><link rel="prefetch" href="/docs/assets/js/71.8b580dcf.js"><link rel="prefetch" href="/docs/assets/js/72.355b7953.js"><link rel="prefetch" href="/docs/assets/js/73.b9ad99cd.js"><link rel="prefetch" href="/docs/assets/js/74.517d9902.js"><link rel="prefetch" href="/docs/assets/js/75.183f30c2.js"><link rel="prefetch" href="/docs/assets/js/76.894100bc.js"><link rel="prefetch" href="/docs/assets/js/77.a896626f.js"><link rel="prefetch" href="/docs/assets/js/79.d0ad637c.js"><link rel="prefetch" href="/docs/assets/js/8.c0e09a5e.js"><link rel="prefetch" href="/docs/assets/js/80.43bf5b47.js"><link rel="prefetch" href="/docs/assets/js/81.a3f44150.js"><link rel="prefetch" href="/docs/assets/js/82.514bee1c.js"><link rel="prefetch" href="/docs/assets/js/83.288e8f5d.js"><link rel="prefetch" href="/docs/assets/js/84.76c28d97.js"><link rel="prefetch" href="/docs/assets/js/85.c70a27f1.js"><link rel="prefetch" href="/docs/assets/js/86.d1d289b7.js"><link rel="prefetch" href="/docs/assets/js/87.bced23ab.js"><link rel="prefetch" href="/docs/assets/js/88.f0049b73.js"><link rel="prefetch" href="/docs/assets/js/89.c2ba01c2.js"><link rel="prefetch" href="/docs/assets/js/9.6121e0b4.js"><link rel="prefetch" href="/docs/assets/js/90.529090e5.js"><link rel="prefetch" href="/docs/assets/js/91.dd59134d.js"><link rel="prefetch" href="/docs/assets/js/92.d3e7c08c.js"><link rel="prefetch" href="/docs/assets/js/93.a12b0826.js"><link rel="prefetch" href="/docs/assets/js/94.036e5ed0.js"><link rel="prefetch" href="/docs/assets/js/vendors~docsearch.0da9b1d4.js">
<link rel="stylesheet" href="/docs/assets/css/0.styles.c7ff573f.css">
</head>
<body>
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/docs/" class="home-link router-link-active"><img src="/docs/logo.png" alt="GrapesJS" class="logo"> <span class="site-name can-hide">GrapesJS</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/docs/" class="nav-link">
Docs
</a></div><div class="nav-item"><a href="/docs/api/" class="nav-link">
API Reference
</a></div><div class="nav-item"><a href="https://opencollective.com/grapesjs" target="_blank" rel="noopener noreferrer" class="nav-link external">
Support Us
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="https://twitter.com/grapesjs" target="_blank" rel="noopener noreferrer" class="nav-link external">
Twitter
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/artf/grapesjs" target="_blank" rel="noopener noreferrer" class="repo-link">
GitHub
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/docs/" class="nav-link">
Docs
</a></div><div class="nav-item"><a href="/docs/api/" class="nav-link">
API Reference
</a></div><div class="nav-item"><a href="https://opencollective.com/grapesjs" target="_blank" rel="noopener noreferrer" class="nav-link external">
Support Us
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="https://twitter.com/grapesjs" target="_blank" rel="noopener noreferrer" class="nav-link external">
Twitter
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/artf/grapesjs" target="_blank" rel="noopener noreferrer" class="repo-link">
GitHub
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <div id="native-carbon" class="carbon-ads"></div> <ul class="sidebar-links"><li><a href="/docs/" aria-current="page" class="sidebar-link">Introduction</a></li><li><a href="/docs/getting-started.html" class="sidebar-link">Getting Started</a></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Modules</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/docs/modules/Components.html" class="sidebar-link">Components</a></li><li><a href="/docs/modules/Components-js.html" class="sidebar-link">Components &amp; JS</a></li><li><a href="/docs/modules/Traits.html" class="sidebar-link">Traits</a></li><li><a href="/docs/modules/Blocks.html" class="sidebar-link">Blocks</a></li><li><a href="/docs/modules/Assets.html" class="sidebar-link">Assets</a></li><li><a href="/docs/modules/Commands.html" class="sidebar-link">Commands</a></li><li><a href="/docs/modules/I18n.html" class="sidebar-link">I18n</a></li><li><a href="/docs/modules/Selectors.html" class="sidebar-link">Selectors</a></li><li><a href="/docs/modules/Layers.html" class="sidebar-link">Layers</a></li><li><a href="/docs/modules/Pages.html" class="sidebar-link">Pages</a></li><li><a href="/docs/modules/Style-manager.html" class="sidebar-link">Style Manager</a></li><li><a href="/docs/modules/Storage.html" class="sidebar-link">Storage Manager</a></li><li><a href="/docs/modules/Modal.html" class="sidebar-link">Modal</a></li><li><a href="/docs/modules/Plugins.html" class="sidebar-link">Plugins</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>Guides</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/docs/guides/Replace-Rich-Text-Editor.html" class="sidebar-link">Replace Rich Text Editor</a></li><li><a href="/docs/guides/Custom-CSS-parser.html" aria-current="page" class="active sidebar-link">Use Custom CSS Parser</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/docs/guides/Custom-CSS-parser.html#import-html-css" class="sidebar-link">Import HTML/CSS</a></li><li class="sidebar-sub-header"><a href="/docs/guides/Custom-CSS-parser.html#cssom-results-are-inconsistent" class="sidebar-link">CSSOM results are inconsistent</a></li><li class="sidebar-sub-header"><a href="/docs/guides/Custom-CSS-parser.html#cssom-results-can-be-nonintuitive" class="sidebar-link">CSSOM results can be nonintuitive</a></li><li class="sidebar-sub-header"><a href="/docs/guides/Custom-CSS-parser.html#set-css-parser" class="sidebar-link">Set CSS parser</a></li><li class="sidebar-sub-header"><a href="/docs/guides/Custom-CSS-parser.html#rule-objects" class="sidebar-link">Rule Objects</a></li><li class="sidebar-sub-header"><a href="/docs/guides/Custom-CSS-parser.html#plugins" class="sidebar-link">Plugins</a></li></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="use-custom-css-parser"><a href="#use-custom-css-parser" class="header-anchor">#</a> Use Custom CSS Parser</h1> <p>If you just use GrapesJS for building templates from scratch, so you start from an empty canvas and for editing you strictly rely on the generated JSON (final HTML/CSS only for end-users) then, probably, you might skip this guide. On the other hand, if you import templates from already defined HTML/CSS or let the user embed custom codes (eg. using the <a href="https://github.com/GrapesJS/components-custom-code" target="_blank" rel="noopener noreferrer">grapesjs-custom-code<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> plugin), then you have to know that you might face strange behaviors.</p> <div class="custom-block warning"><p class="custom-block-title">WARNING</p> <p>This guide requires GrapesJS v0.14.33 or higher</p></div> <p></p><div class="table-of-contents"><ul><li><a href="#import-html-css">Import HTML/CSS</a></li><li><a href="#cssom-results-are-inconsistent">CSSOM results are inconsistent</a><ul><li><a href="#results">Results</a></li></ul></li><li><a href="#cssom-results-can-be-nonintuitive">CSSOM results can be nonintuitive</a></li><li><a href="#set-css-parser">Set CSS parser</a></li><li><a href="#rule-objects">Rule Objects</a></li><li><a href="#plugins">Plugins</a></li></ul></div><p></p> <h2 id="import-html-css"><a href="#import-html-css" class="header-anchor">#</a> Import HTML/CSS</h2> <p>Importing already defined HTML/CSS is a really good feature as it lets you start editing immediately any kind of template and obviously, GrapesJS itself promotes this kind of approach</p> <div class="language-html extra-class"><pre class="language-html"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>gjs<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>txt-red<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>Hello world!<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>style</span><span class="token punctuation">&gt;</span></span><span class="token style"><span class="token language-css"><span class="token selector">.txt-red</span><span class="token punctuation">{</span><span class="token property">color</span><span class="token punctuation">:</span> red<span class="token punctuation">}</span></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>style</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>text/javascript<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
<span class="token keyword">const</span> editor <span class="token operator">=</span> grapesjs<span class="token punctuation">.</span><span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
<span class="token literal-property property">container</span> <span class="token operator">:</span> <span class="token string">'#gjs'</span><span class="token punctuation">,</span>
<span class="token literal-property property">fromElement</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>To work fast and easier GrapesJS needs to compile a simple string (HTML/CSS) into structured nodes (nested JS objects). Fortunately, most of the hard work (parsing) is already done by the browser itself which translates that string into its own objects (<a href="https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model" target="_blank" rel="noopener noreferrer">DOM<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>/<a href="https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model" target="_blank" rel="noopener noreferrer">CSSOM<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>) and so we just rely on those, by traversing them and creating our nodes (unfortunately browser's objects are not enough). The fact we're able to parse our strings just by using the browser itself it's very cool, we can enable the import feature without requiring any third-party library, so... where is the problem? Well, while the generated DOM is performing quite well, as we're able to extract what we need, unfortunately, it's not the same for the CSSOM, so let's see in the next paragraph what is wrong with it.</p> <h2 id="cssom-results-are-inconsistent"><a href="#cssom-results-are-inconsistent" class="header-anchor">#</a> CSSOM results are inconsistent</h2> <p>Unfortunately, we have discovered that the CSSOM generated by browsers are highly inconsistent from what we ask to parse. To demonstrate it, we gonna create a simple example by using the built-in parser and we'll check its result.
So, for our case we just take in account a simple rule, we'll parse it and print the CSSOM result on screen.</p> <div class="language-html extra-class"><pre class="language-html"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>h1</span><span class="token punctuation">&gt;</span></span>To parse<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h1</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>pre</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>css-to-parse<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
.simple-class {
background-image:url(&quot;https://image1.png&quot;), url(&quot;https://image2.jpg&quot;);
background-attachment: fixed, scroll;
background-position:left top, center center;
background-repeat:repeat-y, no-repeat;
background-size: contain, cover;
box-shadow: 0 0 5px #9d7aa5, 0 0 10px #e6c3ee;
border: 2px solid #FF0000;
}
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>pre</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>h1</span><span class="token punctuation">&gt;</span></span>Result<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h1</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>pre</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>result<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>pre</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
<span class="token comment">// We use ES5 just to make it more cross-browser, without the need of being compiled</span>
<span class="token keyword">function</span> <span class="token function">parse</span><span class="token punctuation">(</span><span class="token parameter">str</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">var</span> result <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token comment">// Create the element which will contain the style to parse</span>
<span class="token keyword">var</span> el <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">'style'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
el<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> str<span class="token punctuation">;</span>
<span class="token comment">// We have to append the style to get its CSSOM</span>
document<span class="token punctuation">.</span>head<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>el<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> sheet <span class="token operator">=</span> el<span class="token punctuation">.</span>sheet<span class="token punctuation">;</span>
<span class="token comment">// Now we can remove it</span>
document<span class="token punctuation">.</span>head<span class="token punctuation">.</span><span class="token function">removeChild</span><span class="token punctuation">(</span>el<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> sheet<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span> <span class="token function">CSSOMToString</span><span class="token punctuation">(</span><span class="token parameter">root</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// For the sake of brevity we just print what we need</span>
<span class="token keyword">var</span> styleStr <span class="token operator">=</span> <span class="token string">''</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> rule <span class="token operator">=</span> root<span class="token punctuation">.</span>cssRules<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> style <span class="token operator">=</span> rule<span class="token punctuation">.</span>style<span class="token punctuation">;</span>
<span class="token comment">// The only way we have to iterate over CSSStyleDeclaration</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span> len <span class="token operator">=</span> style<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i <span class="token operator">&lt;</span> len<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">var</span> property <span class="token operator">=</span> style<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> value <span class="token operator">=</span> style<span class="token punctuation">.</span><span class="token function">getPropertyValue</span><span class="token punctuation">(</span>property<span class="token punctuation">)</span><span class="token punctuation">;</span>
styleStr <span class="token operator">+=</span> <span class="token string">&quot;\t&quot;</span> <span class="token operator">+</span> property <span class="token operator">+</span> <span class="token string">': '</span> <span class="token operator">+</span> value <span class="token operator">+</span> <span class="token string">&quot;;\n&quot;</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">var</span> result <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'result'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
result<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> rule<span class="token punctuation">.</span>selectorText <span class="token operator">+</span> <span class="token string">&quot; {\n&quot;</span> <span class="token operator">+</span> styleStr <span class="token operator">+</span> <span class="token string">&quot;}&quot;</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">var</span> css <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'css-to-parse'</span><span class="token punctuation">)</span><span class="token punctuation">.</span>innerText<span class="token punctuation">;</span>
<span class="token function">CSSOMToString</span><span class="token punctuation">(</span><span class="token function">parse</span><span class="token punctuation">(</span>css<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><h3 id="results"><a href="#results" class="header-anchor">#</a> Results</h3> <p>Here some results (using latest versions + IE11)</p> <img src="/docs/cssom-result.jpg"> <p>As you see, this is what we get for asking only 7 properties, who adds more or less, someone converts colors to rgba functions and someone else changes the order of our values (eg. <code>box-shadow</code>). Webkit-based browsers attach also properties they self don't understand</p> <img src="/docs/cssom-devtools.png"> <p>So it's clear that we can't rely on CSSOM objects, that's why we added the possibility to set custom CSS parser via <code>editor.setCustomParserCss</code> method or <code>config.Parser.parserCss</code> option to use on initialization. Let's see in detail how it's expected to work</p> <h2 id="cssom-results-can-be-nonintuitive"><a href="#cssom-results-can-be-nonintuitive" class="header-anchor">#</a> CSSOM results can be nonintuitive</h2> <p>As per current <a href="https://drafts.csswg.org/css-variables-1/#variables-in-shorthands" target="_blank" rel="noopener noreferrer">csswg specification<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> variables in shorthand properties can serialize to the empty string.
This means that while <code>background-color: var(--my-var)</code> will serialize fine <code>background: var(--my-var)</code> will not.</p> <h2 id="set-css-parser"><a href="#set-css-parser" class="header-anchor">#</a> Set CSS parser</h2> <p>The custom parser you have to use it's just a function receiving 2 arguments: <code>css</code>, as the CSS string to parse, and <code>editor</code>, the instance of the current editor. As the result, you should return an array containing valid rule objects, the syntax of those objects are explained below. This is how you can set the custom parser</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> <span class="token function-variable function">parserCss</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">css<span class="token punctuation">,</span> editor</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> result <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token comment">// ... parse the CSS string</span>
result<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
<span class="token literal-property property">selectors</span><span class="token operator">:</span> <span class="token string">'.someclass, div .otherclass'</span><span class="token punctuation">,</span>
<span class="token literal-property property">style</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token literal-property property">color</span><span class="token operator">:</span> <span class="token string">'red'</span> <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token comment">// ...</span>
<span class="token keyword">return</span> result<span class="token punctuation">;</span> <span class="token comment">// Result should be ALWAYS an array</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token comment">// On initialization</span>
<span class="token comment">// This is the recommended way, as you gonna use the parser from the beginning</span>
<span class="token keyword">const</span> editor <span class="token operator">=</span> grapesjs<span class="token punctuation">.</span><span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
<span class="token comment">//...</span>
<span class="token literal-property property">parser</span><span class="token operator">:</span> <span class="token punctuation">{</span>
parserCss<span class="token punctuation">,</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Or later, via editor API</span>
editor<span class="token punctuation">.</span><span class="token function">setCustomParserCss</span><span class="token punctuation">(</span>parserCss<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><h2 id="rule-objects"><a href="#rule-objects" class="header-anchor">#</a> Rule Objects</h2> <p>The syntax of rule objects is pretty straightforward, each object might contain following keys</p> <table><thead><tr><th>Key</th> <th>Description</th> <th>Example</th></tr></thead> <tbody><tr><td><code>selectors</code></td> <td>Selectors of the rule. <br> <strong>REQUIRED</strong> return an empty string in case the rule has no selectors</td> <td><code>.class1, div &gt; #someid</code></td></tr> <tr><td><code>style</code></td> <td>Style declarations as an object</td> <td><code>{ color: 'red' }</code></td></tr> <tr><td><code>atRule</code></td> <td>At-rule name</td> <td><code>media</code></td></tr> <tr><td><code>params</code></td> <td>Parameters of the at-rule</td> <td><code>screen and (min-width: 480px)</code></td></tr></tbody></table> <p>To make it more clear let's see a few examples</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// Input</span>
<span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">
@font-face {
font-family: &quot;Font Name&quot;;
src: url(&quot;https://font-url.eot&quot;);
}
</span><span class="token template-punctuation string">`</span></span>
<span class="token comment">// Output</span>
<span class="token punctuation">[</span>
<span class="token punctuation">{</span>
<span class="token literal-property property">selectors</span><span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">,</span>
<span class="token literal-property property">atRule</span><span class="token operator">:</span> <span class="token string">'font-face'</span><span class="token punctuation">,</span>
<span class="token literal-property property">style</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token string-property property">'font-family'</span><span class="token operator">:</span> <span class="token string">'&quot;Font Name&quot;'</span><span class="token punctuation">,</span>
<span class="token literal-property property">src</span><span class="token operator">:</span> <span class="token string">'url(&quot;https://font-url.eot&quot;)'</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
<span class="token punctuation">]</span>
<span class="token comment">// Input</span>
<span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">
@keyframes keyframe-name {
from { opacity: 0; }
to { opacity: 1; }
}
</span><span class="token template-punctuation string">`</span></span>
<span class="token comment">// Output</span>
<span class="token punctuation">[</span>
<span class="token punctuation">{</span>
<span class="token literal-property property">params</span><span class="token operator">:</span> <span class="token string">'keyframe-name'</span><span class="token punctuation">,</span>
<span class="token literal-property property">selectors</span><span class="token operator">:</span> <span class="token string">'from'</span><span class="token punctuation">,</span>
<span class="token literal-property property">atRule</span><span class="token operator">:</span> <span class="token string">'keyframes'</span><span class="token punctuation">,</span>
<span class="token literal-property property">style</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token literal-property property">opacity</span><span class="token operator">:</span> <span class="token string">'0'</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
<span class="token literal-property property">params</span><span class="token operator">:</span> <span class="token string">'keyframe-name'</span><span class="token punctuation">,</span>
<span class="token literal-property property">selectors</span><span class="token operator">:</span> <span class="token string">'to'</span><span class="token punctuation">,</span>
<span class="token literal-property property">atRule</span><span class="token operator">:</span> <span class="token string">'keyframes'</span><span class="token punctuation">,</span>
<span class="token literal-property property">style</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token literal-property property">opacity</span><span class="token operator">:</span> <span class="token string">'1'</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
<span class="token punctuation">]</span>
<span class="token comment">// Input</span>
<span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">
@media screen and (min-width: 480px) {
body {
background-color: lightgreen;
}
.class-test, .class-test2:hover {
color: blue !important;
}
}
</span><span class="token template-punctuation string">`</span></span>
<span class="token comment">// Output</span>
<span class="token punctuation">[</span>
<span class="token punctuation">{</span>
<span class="token literal-property property">params</span><span class="token operator">:</span> <span class="token string">'screen and (min-width: 480px)'</span><span class="token punctuation">,</span>
<span class="token literal-property property">selectors</span><span class="token operator">:</span> <span class="token string">'body'</span><span class="token punctuation">,</span>
<span class="token literal-property property">atRule</span><span class="token operator">:</span> <span class="token string">'media'</span><span class="token punctuation">,</span>
<span class="token literal-property property">style</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token string-property property">'background-color'</span><span class="token operator">:</span> <span class="token string">'lightgreen'</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
<span class="token literal-property property">params</span><span class="token operator">:</span> <span class="token string">'screen and (min-width: 480px)'</span><span class="token punctuation">,</span>
<span class="token literal-property property">selectors</span><span class="token operator">:</span> <span class="token string">'.class-test, .class-test2:hover'</span><span class="token punctuation">,</span>
<span class="token literal-property property">atRule</span><span class="token operator">:</span> <span class="token string">'media'</span><span class="token punctuation">,</span>
<span class="token literal-property property">style</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token literal-property property">color</span><span class="token operator">:</span> <span class="token string">'blue !important'</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
<span class="token punctuation">]</span>
<span class="token comment">// Input</span>
<span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">
:root {
--some-color: red;
--some-width: 55px;
}
</span><span class="token template-punctuation string">`</span></span>
<span class="token comment">// Output</span>
<span class="token punctuation">[</span>
<span class="token punctuation">{</span>
<span class="token literal-property property">selectors</span><span class="token operator">:</span> <span class="token string">':root'</span><span class="token punctuation">,</span>
<span class="token literal-property property">style</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token string-property property">'--some-color'</span><span class="token operator">:</span> <span class="token string">'red'</span><span class="token punctuation">,</span>
<span class="token string-property property">'--some-width'</span><span class="token operator">:</span> <span class="token string">'55px'</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span>
</code></pre></div><h2 id="plugins"><a href="#plugins" class="header-anchor">#</a> Plugins</h2> <p>Below the list of current available CSS parsers as plugins, if you need to create your own we highly suggest to explore their sources</p> <ul><li><a href="https://github.com/GrapesJS/parser-postcss" target="_blank" rel="noopener noreferrer">grapesjs-parser-postcss<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> - Using <a href="https://github.com/postcss/postcss" target="_blank" rel="noopener noreferrer">PostCSS<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> parser</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/artf/grapesjs/edit/dev/docs/guides/Custom-CSS-parser.md" target="_blank" rel="noopener noreferrer">Edit this page on GitHub</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">Last Updated:</span> <span class="time">2/10/2023, 12:10:15 PM</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
<a href="/docs/guides/Replace-Rich-Text-Editor.html" class="prev">
Replace Rich Text Editor
</a></span> <!----></p></div> </main></div><div class="global-ui"></div></div>
<script src="/docs/assets/js/app.7cba500a.js" defer></script><script src="/docs/assets/js/4.0070552e.js" defer></script><script src="/docs/assets/js/2.6fefd022.js" defer></script><script src="/docs/assets/js/1.d23e9fed.js" defer></script><script src="/docs/assets/js/78.a8d38215.js" defer></script>
</body>
</html>