For better theming purposes, for theming the "purchased entity" section of the "add-to-cart" area of a product entity display, the HTML markup for commerce product attributes needs to include the "product attribute type" so that such elements can be themed individually on a "product attribute type" basis. The current markup does not include this information.
Using actual the markup from a test product entity as an example, shown below, it seems like the - fieldset - element might be the best place to include both the "product attribute type" machine name and the machine name of the specific element within the product variation within the fieldset element's CSS classes. Currently, the CSS classes for the fieldset element HTML markup is :
<fieldset class="fieldgroup form-composite required js-form-item form-item js-form-wrapper form-wrapper"> </>
which doesn't include any commerce entity identification at all. Both the product attribute type machine name and identification of the specific attribute set (although the fieldset element ID includes the specific identity of the individual product attribute set).
At any further into the markup hierarchy (see below), it is too late to identify the - product attribute type - to which the inner elements belong, because the markup has already reached specific components, such as the - legend - element in the example below, which provides the label/title for the product attribute radio button set. The example below implements example clothing sizes.
(actual example markup for a radio button set for product size with element XS S M L XL)
<fieldset data-drupal-selector="edit-purchased-entity-0-attributes-attribute-prod-attr-size" id="edit-purchased-entity-0-attributes-attribute-prod-attr-size--wrapper" class="fieldgroup form-composite required js-form-item form-item js-form-wrapper form-wrapper" required="required" aria-required="true">
<legend>
<span class="fieldset-legend js-form-required form-required">Size</span>
</legend>
<div class="fieldset-wrapper">
<div id="edit-purchased-entity-0-attributes-attribute-prod-attr-size" class="form-radios">
<div class="js-form-item form-item js-form-type-radio form-type-radio js-form-item-purchased-entity-0-attributes-attribute-prod-attr-size form-item-purchased-entity-0-attributes-attribute-prod-attr-size">
<input data-drupal-selector="edit-purchased-entity-0-attributes-attribute-prod-attr-size-3" type="radio" id="edit-purchased-entity-0-attributes-attribute-prod-attr-size-3" name="purchased_entity[0][attributes][attribute_prod_attr_size]" value="3" checked="checked" class="form-radio" />
<label for="edit-purchased-entity-0-attributes-attribute-prod-attr-size-3" class="option">XS</label>
</div>
<div class="js-form-item form-item js-form-type-radio form-type-radio js-form-item-purchased-entity-0-attributes-attribute-prod-attr-size form-item-purchased-entity-0-attributes-attribute-prod-attr-size">
<input data-drupal-selector="edit-purchased-entity-0-attributes-attribute-prod-attr-size-4" type="radio" id="edit-purchased-entity-0-attributes-attribute-prod-attr-size-4" name="purchased_entity[0][attributes][attribute_prod_attr_size]" value="4" class="form-radio" />
<label for="edit-purchased-entity-0-attributes-attribute-prod-attr-size-4" class="option">S</label>
</div>
<div class="js-form-item form-item js-form-type-radio form-type-radio js-form-item-purchased-entity-0-attributes-attribute-prod-attr-size form-item-purchased-entity-0-attributes-attribute-prod-attr-size">
<input data-drupal-selector="edit-purchased-entity-0-attributes-attribute-prod-attr-size-5" type="radio" id="edit-purchased-entity-0-attributes-attribute-prod-attr-size-5" name="purchased_entity[0][attributes][attribute_prod_attr_size]" value="5" class="form-radio" />
<label for="edit-purchased-entity-0-attributes-attribute-prod-attr-size-5" class="option">M</label>
</div>
<div class="js-form-item form-item js-form-type-radio form-type-radio js-form-item-purchased-entity-0-attributes-attribute-prod-attr-size form-item-purchased-entity-0-attributes-attribute-prod-attr-size">
<input data-drupal-selector="edit-purchased-entity-0-attributes-attribute-prod-attr-size-6" type="radio" id="edit-purchased-entity-0-attributes-attribute-prod-attr-size-6" name="purchased_entity[0][attributes][attribute_prod_attr_size]" value="6" class="form-radio" />
<label for="edit-purchased-entity-0-attributes-attribute-prod-attr-size-6" class="option">L</label>
</div>
<div class="js-form-item form-item js-form-type-radio form-type-radio js-form-item-purchased-entity-0-attributes-attribute-prod-attr-size form-item-purchased-entity-0-attributes-attribute-prod-attr-size">
<input data-drupal-selector="edit-purchased-entity-0-attributes-attribute-prod-attr-size-7" type="radio" id="edit-purchased-entity-0-attributes-attribute-prod-attr-size-7" name="purchased_entity[0][attributes][attribute_prod_attr_size]" value="7" class="form-radio" />
<label for="edit-purchased-entity-0-attributes-attribute-prod-attr-size-7" class="option">XL</label>
</div>
</div>
</div>
</fieldset>
(enlarged image of markup for easier reading)

----
With the currently available markup, it is possible to theme radio button sets within product display add-to-cart area, the available classes do not identify the current context based on - product attribute type - so that each - product attribute type - option set can be styled individually.
(actual selectors extracted from the real-life example HTML markup above)
.commerce-order-item-add-to-cart-form
{
}
.commerce-order-item-add-to-cart-form .form-item legend
{
}
.commerce-order-item-add-to-cart-form .fieldset-legend.form-required
{
}
.commerce-order-item-add-to-cart-form .fieldset-legend.form-required:after
{
}
.commerce-order-item-add-to-cart-form .fieldset-wrapper
{
}
.commerce-order-item-add-to-cart-form .fieldset-wrapper .form-radios
{
}
.commerce-order-item-add-to-cart-form .fieldset-wrapper .form-radios .form-type-radio
{
}
.commerce-order-item-add-to-cart-form .fieldset-wrapper .form-radios .form-radio
{
}
.commerce-order-item-add-to-cart-form .fieldset-wrapper .form-radios .form-type-radio .option
{
}
.commerce-order-item-add-to-cart-form .fieldset-wrapper .form-radios .form-radio:active + .option
{
}
.commerce-order-item-add-to-cart-form .fieldset-wrapper .form-radios .form-radio:hover + .option
{
}
.commerce-order-item-add-to-cart-form .fieldset-wrapper .form-radios .form-radio:checked + .option
{
}
Below is an image of styling performed on the radio button set using the markup above, but it would apply to EVERY radio button set within the add-to-cart form/area, rather than to a radio button set for a specific - product attribute type - entity. If the product attribute type machine name were available it would fix this problem.

Alternatively, is there some way within the DC 2.x Admin GUI to add more information that would produce more specific HTML markup and CSS classes? However, it just seems like putting the - product attribute type - machine name in the fieldset would provide every sitebuilding with the precise information needed for optimal product attribute set element theming.
Submitting bug reports to help make Drupal 8 Commerce the best it might be.
| Comment | File | Size | Author |
|---|---|---|---|
| #5 | product-and-attributes-class-2912933-5.patch | 2.17 KB | drugan |
| d8dc-product-attribute-styling-example-0001.png | 14.68 KB | websiteworkspace | |
| d8dc-product-attribute-html-markup-example-0001.png | 80.37 KB | websiteworkspace |
Comments
Comment #2
websiteworkspace commentedThis CSS class markup omission is a serious problem.
Without the entity type machine names included at various levels of the markup, theming and front end development with DC2x is currently extremely limited.
At the level of the fieldset element the ID included in the markup includes the machine name of the product attribute type:
"edit-purchased-entity-0-attributes-attribute-prod-attr-size--wrapper"
wherein - prod-attr-size - is the machine name of the attribute type. This means that the necessary information is available. However, this essential information is not included in the list of classes, which are:
class="fieldgroup form-composite required js-form-item form-item js-form-wrapper form-wrapper"If the class markup looked like:
class="fieldgroup form-composite required js-form-item form-item js-form-wrapper form-wrapper prod-attr-size"With this very necessary code addition, theme CSS could specifically target the product attribute type machine name, in this example - prod-attr-size - for implementation of a GUI component for that particular type of size UI element targeting the product attribute type machine name.
Currently, there doesn't appear to be any way to do this, since the DC2x code does not insert the product type, product variation type, or product attribute type, - machine names - into the HTML markup it creates anywhere at the appropriate levels of the HTML produced by DC2x.
Comment #3
websiteworkspace commentedComment #4
bojanz commented"Critical" is for bugs that crash the entire system. Theming limitations are not critical.
I have referred this issue to our contributors. Someone will patch it over time.
Comment #5
drugan commentedFlush caches and look for the article and fieldset elements.
Comment #6
websiteworkspace commented@drugan
Thank you for building a patch.
I will install the patch on a test site.
I will look also forward to this in the future, once it has been committed and updates are possible.
(too many problems with D8.4.0 at the moment)
At present it seems the only workaround possible for this this deployment problem is using the following style of CSS selector lookup:
fieldset[id*="prod-attr-machinename"]
which really slows page rendering. The fieldset element is the only element at an appropriate level that in the current version includes entity type identifying information
(example usage)
p.s. this type of missing markup problem exists through the commerce HTML markup hierarchy, including product type and product variation type. This type of markup is also important for being able to create a - product type - aware commerce product .twig template, which is extremely important, and a sorely missing feature at the moment, that blocks certain kinds of functionality.
Comment #7
drugan commentedWhen you apply the patch then you can do this:
Comment #8
anybody