Edit in GitHubLog an issue

Code demarcation standard

Core developers must follow the code demarcation standard.

This standard is recommended for third-party extension developers.

Some parts of code might not comply with the standard, but we are working to gradually improve this.

The standard was developed in the scope of our efforts to ensure the following:

  • Decouple visual (CSS) layer from the functional (JavaScript) layer.
  • Decouple functional (JavaScript) layer from the markup (HTML).
  • Reinstate emphasis on using of jQuery templates.
  • Reinstate emphasis on decoupling HTML, CSS and JS from PHP classes.

Use RFC 2119 to interpret the "MUST," "MUST NOT," "REQUIRED," "SHALL," "SHALL NOT," "SHOULD," "SHOULD NOT," "RECOMMENDED," "MAY," and "OPTIONAL" keywords.

Semantics#

Attribute names and values#

For attribute names and values you must use meaningful unabbreviated lowercase words comprised of Latin characters concatenated with a hyphen (-)

  • Helps simplify and unify naming conventions that are used to apply visual styles to page elements.

Acceptable:

Copied to your clipboard
1<section id="information-dialog-tree">
2 <p> ... </p>
3 <p> ... </p>
4</section>
5<a href="#information-dialog-tree">Scroll to text</a>

Unacceptable:

Copied to your clipboard
1<section id="some_id">
2 <p> ... </p>
3 <p> ... </p>
4</section>
5<section id="some_id">
6 <p> ... </p>
7 <p> ... </p>
8</section>
9<a href="#some_id">Scroll to text</a>

Attribute IDs#

Semantic representation may rely on ID attribute

  • Forces engineers to think about reusable page components instead of unique singleton components.
  • Reduces long-term maintenance efforts.

Acceptable PHTML template:

The following acceptable example is terse and uses an Accessible Rich Internet Applications (ARIA) approach.

Copied to your clipboard
1<ul>
2 <li class="first" type="button" aria-pressed="false" aria-controls="some-id">button 1</li>
3 <li type="button" aria-pressed="false" aria-controls="some-id">button 2</li>
4 <li type="button" aria-pressed="true" aria-controls="some-id">button 3</li>
5</ul>
6<div>
7 <label for="some-id">Enter text</label>
8 <textarea id="some-id"></textarea>
9</div>
10<a href="#some-id">Scroll to text</a>

Unacceptable combination of PHTML, JavaScript, and CSS files:

The following unacceptable example replaces a single PHTML file with a combination of a PHTML, JavaScript, and CSS files.

PHTML file:

Copied to your clipboard
1<ul id="my-special-menu">
2 <li id="buttonId1" class="first" type="button">button 1</li>
3 <li id="buttonId2" type="button">button 2</li>
4 <li id="buttonId3" type="button">button 3</li>
5</ul>

JavaScript file:

Copied to your clipboard
$('#my-special-menu').on('click','li[id^="button"]', function() { ... })

CSS file:

Copied to your clipboard
1#my-special-menu { ... }
2#my-special-menu > li { ... }

Presentation and content#

You must follow the separation of presentation and content methodology

The following list will help you make a distinction between the actual meaning of a document, and how this meaning is presented to its readers:

Content (Semantics) includes:

  • logic
  • information
  • data
  • model
  • outline
  • message

Presentation includes:

  • aesthetic
  • graphics
  • design
  • style
  • visualization
  • view

HTML markup#

You must use semantic HTML markup only, and must not use presentation markup

Acceptable:

Copied to your clipboard
1<p>HTML has been created to <strong>semantically</strong> represent documents.</p>
2<p><strong>Warning:</strong> Following the procedure described below may irreparably damage your equipment.</p>

Unacceptable:

Copied to your clipboard
1<p>HTML has been created to <b>semantically</b> represent documents.</p>
2<p><b>Warning:</b> Following the procedure described below may irreparably damage your equipment.</p>

Code demarcation#

Visual representation#

Visual representation must rely only on HTML class attributes, CSS pseudo-classes and pseudo-elements, HTML tags, and form element's type attribute and form elements state attributes (example: disabled, checked).

As the first option, you are required to use HTML class attributes. In case this option is not applicable then it is recommended to use HTML tags and form element's type attribute.

  • Enforces clean, strict separation between visual and business logic layers.
  • Allows frontend and backend teams to work independently.
  • Allows changing look and feel without affecting business functionality, and vice versa.
  • Enables frontend teams to clean up old styles quickly and easily when refactoring.

Acceptable CSS selectors:

Copied to your clipboard
1.notices-wrapper { ... }
2.page-header:after { ... }
3.payment-list:first-child { ... }
4.caution { ... }
5.caution.link { ... }
6form input[type="password"] { ... }
7.control-text:focus { ... }
8a:hover { ... }
9nav li._active { ... }

Unacceptable CSS selectors:

Copied to your clipboard
1#header { ... }
2[data-action="delete"] { ... }
3form input[name="password"] { ... }
4section[role="main"] { ... }
5[role="menu"] [role="menuitem"] { ... }
6[role="menu"] [role="menuitem"].active { ... }

Hard-coded CSS styles#

You must not hard-code CSS styles in JavaScript files

Exception: CSS attributes where values must be calculated beyond the css-topics/LESS code.

  • Simplifies change of the default look and feel by adding CSS classes to and removing them from elements.
  • Improves style extensibility.
  • Reduces long-term maintenance efforts by containing CSS styles in a single place.'

Acceptable JavaScript widget file:

Copied to your clipboard
1...
2 options: {
3 hOffset: 0,
4 myCustomElement: '[data-container="my-custom-element"]',
5 hiddenClass: '_hidden'
6 }
7...
8 this.element.toggleClass(this.options.hiddenClass);
9...
10 this.options.hOffset = /* calculation based on dimensions of some DOM elements within a widget */
11 this.element.find(this.options.myCustomElement).css({'margin-top', this.options.hOffset + 'px'});
12...

Unacceptable JavaScript file:

Copied to your clipboard
1this.element.on('click', function() {
2 if ($(this).is(':visible')) {
3 $(this).css({ visibility: 'hidden' });
4 } else {
5 $(this).css({ visibility: 'visible' });
6 }
7});

Inline CSS styles#

You must not use inline CSS styles inside HTML tags

  • Improves style extensibility allowing engineers to overload styles easier by toggling classes.
  • Enforces clean, strict separation between visual presentation and markup.
  • Enables frontend teams quickly and easily clean up old styles.

Acceptable PHTML template:

Copied to your clipboard
<div class="no-display"> ... </div>

Unacceptable PHTML template:

Copied to your clipboard
<div style="display: none;"> ... </div>

Business logic and JavaScript#

Business logic must rely on only the form, form element name attributes, or data attributes

  • Enforces clean, strict separation between visual and business logic layers.
  • Allows frontend and backend teams to work independently.
  • Allows changing business logic without affecting styling and vice versa.

Acceptable PHTML template:

Copied to your clipboard
1<div data-action="delete" data-mage-init="{myWidget: [option1: 'string']}"></div>
2<div data-role="tooltip">More details</div>

Acceptable JavaScript file:

Copied to your clipboard
1options {
2 deleteAction: '[data-action="delete"]',
3 tooltip: '[data-role="tooltip"]'
4}
5...
6this.element.find(this.options.deleteAction).on( ... );
7this.element.on('click', this.options.deleteAction , function() { ... });
8...
9// Globally initialized widgets
10$( this.options.tooltip).tooltip(); // Globally for ALL tooltip elements
11...

Unacceptable PHTML file:

Copied to your clipboard
<div id="my-widget"></div>

Unacceptable JavaScript file:

Copied to your clipboard
1$('#my-widget').doSomething();
2$('.parent').on('click', '.button', function() { ... });
3$('form').validate();
4$('[role="menu"]').navigation();

HTML helper classes#

You must assign HTML helper classes in JavaScript to modify presentation layer

HTML helper class names added in JavaScript REQUIRE underscore symbol ("_") at the beginning and must be written in lowercase.

Acceptable:

Copied to your clipboard
1<div class="tab-element _active">Content</div>
2<div class="sales-transactions _open">Content</div>
3<div class="billing-agreement _expanded">Content</div>
4<div class="sales-report _hidden">Content</div>

Unacceptable:

Copied to your clipboard
1<div class="tab-element active">Content</div>
2<div class="sales-transactions open">Content</div>
3<div class="billing-agreement expanded">Content</div>
4<div class="sales-report hidden">Content</div>

DOM elements#

You must not select DOM elements based on HTML structure

  • Allows frontend teams to modify markup and themes without affecting business logic.

Acceptable JavaScript file:

Copied to your clipboard
1this.element.find('[data-action="edit"]');
2this.elements.closest('[data-container]');

Unacceptable JavaScript file:

Copied to your clipboard
1this.element.children().children().html('hello world');
2this.element.parent().find('[data-action="edit"]').data('entity_id');

jQuery templates#

You must use jQuery templates to insert recurring markup into DOM structure

  • Reinstates emphasis on jQuery templates. For more information, see JavaScript Coding Best Practices.
  • Reduces long-term maintenance efforts by having markup code stored in one place.
  • Simplifies frontend debugging efforts.

PHTML templates and PHP files#

Hard-coded CSS styles#

You must not hard-code inline CSS styles in PHP classes

  • Reduces long-term maintenance efforts by having styles stored in one place.
  • Simplifies debugging and reduces number of files to be modified.
  • Makes styles more extensible and easier to override when needed.

Acceptable PHP file:

Copied to your clipboard
1...
2$fieldset->addField('new_category_parent', 'text', [
3 'label' => __('Parent Category'),
4 'title' => __('Parent Category'),
5 'required' => true,
6 'class' => 'parent category',
7]);
8...

Unacceptable PHP file:

Copied to your clipboard
1...
2$fieldset->addField('new_category_parent', 'text', [
3 'label' => __('Parent Category'),
4 'title' => __('Parent Category'),
5 'required' => true,
6 'style' => 'border: 1px solid #ccc;',
7]);
8...

Inline JavaScript#

You must not hard-code inline JavaScript in PHP classes

  • Reduces long term maintenance by having frontend business logic stored in one place.
  • Reduces the number of files to be modified.

Acceptable PHP file:

Copied to your clipboard
1...
2public function getSelectorOptions()
3{
4 return $selectorOptions;
5}
6...

Acceptable PHTML template:

Copied to your clipboard
1...
2<div data-mage-init="{treeSuggest: [<?php echo $this->getSelectorOptions(); ?>]}"></div>
3...

or

Acceptable PHTML template:

Copied to your clipboard
1...
2<div data-role="treeSuggest"></div>
3<script type="text/x-magento-init">
4{
5 "[data-role='treeSuggest']": {
6 "treeSuggest": <?php echo $this->getSelectorOptions(); ?>
7 }
8}
9</script>
10...

Unacceptable PHP file:

Copied to your clipboard
1...
2public function getAfterElementHtml()
3{
4 return <<<HTML
5<script>
6jQuery('#{$htmlId}-suggest').treeSuggest({$selectorOptions});
7</script>
8...

Unacceptable PHTML template:

Copied to your clipboard
<?php echo $this->getAfterElementHtml(); ?>

HTML markup#

You must not hard-code HTML markup (used in the <body> tag) in PHP classes

  • Reduces long-term maintenance efforts by having markup stored in one place.
  • Reduces the number of files to be modified.

Acceptable PHP file:

Copied to your clipboard
1...
2public function getAttributeName($element)
3{
4 return ($element->getExtType() === 'multiple') ? $element->getId() . '_checkbox' : NULL;
5}
6
7public function getAttributeId($element)
8{
9 return $element->getId();
10}
11...

Acceptable PHTML template:

Copied to your clipboard
1<span class="attribute-change-checkbox">
2<label>
3 <input type="checkbox"
4 <?php echo ($this->getAttributeName($element)) ? ' name="' . $this->getAttributeName($element) . '"' : NULL; ?>
5 data-mage-init="{customToggleWidget: [elementSelector: "input[name='someCustomName']"]}" />
6 <?php echo __('Change'); ?>
7</label>
8</span>
9<!-- jQuery.hide() code can be either located in the widget itself OR can ask PHP Block class whether or not 'weight_and_type_switcher' should be visible. Based on this condition CSS can be applied to hide/show those elements. -->

Unacceptable PHP file:

Copied to your clipboard
1...
2public function getCheckbox($elementName){
3 $elementNameTag = $this->getAttributeName($elementName) ? 'name="' . $this->getAttributeName($elementName) . '"' : NULL;
4 $tpl = "<input type=\"checkbox\" {$elementNameTag} data-mage-init=\"{customToggleWidget: [elementSelector: \"input[name='someCustomName']\"]}\" />";
5 return $tpl;
6}
7...

Unacceptable PHTML template:

Copied to your clipboard
1<span class="attribute-change-checkbox">
2 <label>
3 <?php echo $this->getCheckbox($element)?>
4 <?php echo __('Change'); ?>
5 </label>
6</span>
7<!-- jQuery.hide() code can be either located in the widget itself OR can ask PHP Block class whether or not 'weight_and_type_switcher' should be visible. Based on this condition CSS can be applied to hide/show those elements. -->
  • Privacy
  • Terms of Use
  • Do not sell my personal information
  • AdChoices
Copyright © 2022 Adobe. All rights reserved.