Clothing Size Chart Development for 1C-Bitrix
The main reason for returns in fashion retail is size mismatch. A size chart on the product card reduces returns by 20–40% depending on the category. However, 1C-Bitrix has no built-in size chart. It must be designed and developed — taking into account that the same clothing may be sold in RU, EU, US, and UK sizes simultaneously, and sizing data varies by brand.
Size Data Storage Architecture
The wrong approach — hardcoding a size chart into the component template. A month later a second brand with a different size grid will appear, and everything will need to be rebuilt.
The right approach — storing size charts as database entities linked to brands and categories.
Custom tables:
CREATE TABLE b_size_charts (
ID SERIAL PRIMARY KEY,
NAME VARCHAR(255) NOT NULL, -- "Men's Nike T-Shirts"
CATEGORY VARCHAR(100), -- 'tops', 'bottoms', 'outerwear', 'underwear'
BRAND_ID INT, -- reference to the brands infoblock
GENDER VARCHAR(10), -- 'male', 'female', 'unisex', 'kids'
ACTIVE BOOLEAN DEFAULT TRUE
);
CREATE TABLE b_size_chart_rows (
ID SERIAL PRIMARY KEY,
CHART_ID INT NOT NULL REFERENCES b_size_charts(ID),
SIZE_RU VARCHAR(10), -- 42, 44, 46...
SIZE_EU VARCHAR(10), -- XS, S, M, L...
SIZE_US VARCHAR(10), -- 6, 8, 10...
SIZE_UK VARCHAR(10),
CHEST_CM NUMERIC(5,1), -- chest circumference, cm
WAIST_CM NUMERIC(5,1),
HIPS_CM NUMERIC(5,1),
HEIGHT_FROM SMALLINT, -- height from, cm
HEIGHT_TO SMALLINT, -- height to, cm
SORT INT DEFAULT 100
);
Linking a Size Chart to a Product
A product in the Bitrix catalog gets a SIZE_CHART_ID property of type "Number" — the ID of the required size chart. This allows:
- Different brands to have different charts
- Different categories (tops/bottoms/footwear) to use different charts
- An individual product to have a specific chart, different from the category default
If SIZE_CHART_ID is not set on the product, the component looks for the default chart for the section (infoblock). This is done via the b_iblock_section section property:
// In the size chart component.php
$chartId = $arResult['PROPERTIES']['SIZE_CHART_ID']['VALUE'];
if (!$chartId) {
// Use the default chart for the section or brand
$chartId = SizeChartTable::getDefaultForSection($arResult['IBLOCK_SECTION_ID']);
}
Size Chart Component
The custom:catalog.size.chart component — a modal window or tab on the product card:
component.php — data retrieval:
$chart = SizeChartTable::getByPrimary($chartId)->fetch();
$rows = SizeChartRowTable::getList([
'filter' => ['=CHART_ID' => $chartId, '=ACTIVE' => true],
'order' => ['SORT' => 'ASC'],
])->fetchAll();
$this->arResult = ['CHART' => $chart, 'ROWS' => $rows];
$this->IncludeComponentTemplate();
template.php — table rendering:
echo '<table class="size-chart">';
echo '<tr><th>RU</th><th>EU</th><th>US</th><th>Chest (cm)</th><th>Waist (cm)</th><th>Hips (cm)</th></tr>';
foreach ($arResult['ROWS'] as $row) {
echo '<tr>';
echo '<td>' . htmlspecialchars($row['SIZE_RU']) . '</td>';
echo '<td>' . htmlspecialchars($row['SIZE_EU']) . '</td>';
// ...
echo '</tr>';
}
echo '</table>';
Component caching: the size chart changes infrequently, cache for 24 hours:
if ($this->StartResultCache(86400, 'size_chart_' . $chartId)) {
// ...
$this->EndResultCache();
}
Interactive Highlighting of the Selected Size
When the user selects a trade offer (size) on the product card, the corresponding row in the size chart is highlighted. This requires synchronization between the trade offer selection component and the size chart.
A trade offer in Bitrix stores the size as the SIZE_VALUE property. This value is passed to JS:
// On trade offer selection
document.querySelectorAll('[data-offer-id]').forEach(btn => {
btn.addEventListener('click', function() {
const sizeValue = this.dataset.sizeValue; // '44' or 'M'
highlightSizeInChart(sizeValue);
});
});
function highlightSizeInChart(size) {
document.querySelectorAll('.size-chart tr').forEach(row => {
row.classList.remove('highlighted');
if (row.dataset.sizeRu === size || row.dataset.sizeEu === size) {
row.classList.add('highlighted');
}
});
}
Size Advisor
A simple calculator: the user enters their measurements and receives a size recommendation.
function recommendSize(chest, waist, hips) {
const chartData = window.sizeChartData; // passed from PHP as JSON
for (const row of chartData) {
if (chest >= row.chest_min && chest <= row.chest_max &&
waist >= row.waist_min && waist <= row.waist_max) {
return { sizeRu: row.size_ru, sizeEu: row.size_eu };
}
}
return null; // no matching size
}
The advisor form — three input fields (chest, waist, hips) + a "Find My Size" button. The result — the recommended row is highlighted in the chart and the corresponding trade offer is automatically selected.
Managing Charts in the Admin Panel
Content managers need a convenient interface for managing size charts without directly editing the database. This is implemented as a custom section in /bitrix/admin/:
/bitrix/admin/size_charts.php — chart list
/bitrix/admin/size_chart_edit.php — edit chart and rows
Alternatively via an infoblock with a non-standard structure — if the standard Bitrix interface is preferred, though it is less flexible for tabular data.
Mobile Version
On mobile devices, a table with 6–8 columns does not fit. Solutions:
-
Horizontal scrolling of the table with
overflow-x: auto— minimal effort - Card format — each size as a separate card with key parameters
- Collapsible rows — show only RU/EU columns, the rest on tap of "More details"
Timeframes
| Scope | Includes | Timeframe |
|---|---|---|
| 1 chart for 1 category | DB, component, display on product card | 3–5 days |
| Multi-brand charts | + admin management, brand linking | 1–2 weeks |
| + Size advisor | + calculator, trade offer highlighting | +3–5 days |
A size chart is not a content block — it is a conversion tool. Correctly implemented, it pays for itself through reduced returns in the first month after launch.







