sizingfashion-techalgorithmecommercedeveloper-guide

Fabric Properties and Sizing Accuracy: What the Body Measurement API Doesn't Know

· 5 min read · Martin Hejda

A body measurement prediction tells you that a user’s chest circumference is approximately 940mm. What it doesn’t tell you is whether that means they should order a size M or a size L in a specific garment. The missing variable is the garment itself.

Clothing size is not purely a function of body dimensions. It’s a function of body dimensions relative to garment dimensions, which depend on fabric properties and cut. A 940mm chest fits differently in a fitted woven cotton shirt with zero stretch than in a performance athletic top with 40% stretch.

If your size recommendation system treats all garments identically, you’re leaving a significant source of recommendation error unaddressed.


The gap: body measurement vs. garment fit

Body dimension APIs return predicted measurements of the body. Garment dimensions are a separate data domain:

  • Finished garment measurements: The actual chest, waist, and hip measurements of a specific garment at a specific size, as produced
  • Ease allowance: The additional space built into a garment beyond the body measurement, which determines how the garment drapes
  • Stretch percentage: How much the fabric extends under normal wear tension
  • Recovery: How much the fabric returns to its original shape after stretching

Together, these determine the effective “body range” that a garment fits.


Ease allowances

Every garment has ease built in — space between the body and the garment that allows movement and creates the desired silhouette. Ease is not an accident; it’s a design decision.

Negative ease: The garment is smaller than the body measurement. The fabric stretches to fit. Common in athletic wear, swimwear, compression garments. A garment with -5% ease on chest circumference means a 940mm chest fits into a garment with a 893mm finished chest measurement.

Zero ease: The garment matches the body measurement exactly. Creates a very fitted look. Uncommon in casualwear; seen in tailored garments.

Standard ease: Typically 5–10cm on chest for casual tops, 2–5cm for trousers at the waist. The garment is larger than the body, creating room for movement and comfort.

Design ease: Additional space beyond standard ease, added for style — a boxy t-shirt may have 10–15cm of design ease, intentionally oversized.

from dataclasses import dataclass

@dataclass
class GarmentSpec:
    brand: str
    product_id: str
    category: str  # "woven_top", "knit_top", "athletic_top", etc.
    
    # Finished garment measurements at each size (mm)
    size_measurements: dict[str, dict[str, int]]  # size_label -> {dimension -> mm}
    
    # Fabric properties
    stretch_pct: float  # 0 = no stretch, 0.4 = 40% stretch
    fabric_weight: str  # "lightweight", "midweight", "heavyweight"
    
    # Fit intent
    fit_type: str  # "fitted", "regular", "relaxed", "oversized"
    
    def effective_body_range(self, size_label: str) -> dict:
        """
        Calculate the body measurement range this size will fit,
        accounting for fabric stretch.
        """
        finished = self.size_measurements.get(size_label, {})
        if not finished:
            return {}
        
        ranges = {}
        for dim, finished_mm in finished.items():
            # At max stretch, the garment accommodates: finished_mm * (1 + stretch_pct)
            # Below finished_mm is still comfortable with appropriate ease
            ranges[dim] = {
                "min_body_mm": finished_mm - 30,  # 30mm below finished = typical ease
                "max_body_mm": int(finished_mm * (1 + self.stretch_pct))
            }
        
        return ranges

The stretch factor in size recommendation

For non-stretch fabrics (woven cotton, denim, linen), the size recommendation is straightforward: the user’s body measurement should fall within the range defined by the finished garment measurements plus standard ease.

For stretch fabrics, the logic inverts: the user’s body measurement can exceed the finished garment measurement by up to stretch_pct × finished_measurement. A 940mm chest can fit into a performance top with 880mm finished chest measurement if the fabric has 15% stretch (880 × 1.15 = 1012mm maximum capacity).

def recommend_size_with_stretch(
    body_chest_mm: int,
    body_waist_mm: int,
    garment_spec: GarmentSpec,
    priority_dimension: str = "chest"
) -> dict:
    """
    Recommend a size accounting for fabric stretch properties.
    """
    best_size = None
    best_score = float("inf")
    
    for size_label, measurements in garment_spec.size_measurements.items():
        finished_mm = measurements.get(priority_dimension)
        if not finished_mm:
            continue
        
        max_body_mm = int(finished_mm * (1 + garment_spec.stretch_pct))
        
        # Determine if body measurement fits within this size's effective range
        # Below finished: comfortable but loose
        # Between finished and max_body: comfortable, appropriate stretch
        # Above max_body: too tight, fabric at full stretch
        if body_chest_mm <= finished_mm:
            # Body is smaller than garment — loose fit
            score = (finished_mm - body_chest_mm) * 0.5  # Penalty for looseness
        elif body_chest_mm <= max_body_mm:
            # Body is within stretch range — ideal fit for athletic wear
            stretch_used = (body_chest_mm - finished_mm) / (max_body_mm - finished_mm)
            score = abs(0.5 - stretch_used) * 20  # Best when 50% of stretch is used
        else:
            # Body exceeds stretch capacity — size too small
            score = (body_chest_mm - max_body_mm) * 3  # Heavy penalty
        
        if score < best_score:
            best_score = score
            best_size = size_label
    
    # Determine confidence
    confidence = "HIGH" if best_score < 15 else "MEDIUM" if best_score < 40 else "LOW"
    
    return {
        "recommended_size": best_size,
        "confidence": confidence,
        "fit_type": garment_spec.fit_type,
        "stretch_category": "stretch" if garment_spec.stretch_pct > 0.1 else "non-stretch"
    }

Fit type modifiers

The same body dimension and the same size chart produce different optimal sizes depending on the user’s fit preference. A user who prefers relaxed fit should size up; a user who prefers fitted should size down or stay at the base recommendation.

FIT_PREFERENCE_MODIFIER = {
    "extra_fitted": -1,   # One size smaller than base recommendation
    "fitted": 0,          # Base recommendation
    "regular": 0,         # Base recommendation  
    "relaxed": +1,        # One size larger
    "oversized": +2       # Two sizes larger
}

def apply_fit_preference(
    base_recommendation: str,
    size_order: list[str],  # e.g., ["XS", "S", "M", "L", "XL", "XXL"]
    user_preference: str = "regular"
) -> dict:
    """
    Shift the size recommendation based on user's fit preference.
    """
    modifier = FIT_PREFERENCE_MODIFIER.get(user_preference, 0)
    
    if base_recommendation not in size_order:
        return {"recommended_size": base_recommendation, "preference_applied": False}
    
    base_idx = size_order.index(base_recommendation)
    adjusted_idx = max(0, min(len(size_order) - 1, base_idx + modifier))
    
    return {
        "recommended_size": size_order[adjusted_idx],
        "base_recommendation": base_recommendation,
        "preference_applied": modifier != 0,
        "shift": modifier,
        "user_preference": user_preference
    }

Practical data collection: garment measurements

To implement garment-specific recommendations, you need finished garment measurements for each size of each product. Sources:

Brand-provided data: Many brands include “Product Measurements” or “Garment Measurements” on product pages — this is the finished measurement of the specific garment, distinct from the “Size Guide” which shows body measurements.

Manual measurement program: For smaller catalogs, measure physical samples. This is time-consuming but produces the most accurate data.

Size grading formulas: Some brands use standard grading rules (adding fixed amounts per size). If you know the base size measurements and the grading increments, you can compute measurements for all sizes.

User-generated data: Fit feedback from users who purchased can be reverse-engineered to estimate garment measurements. If users who measured 940mm chest consistently say size M fits them, you have a data point about M’s effective body range.


What to tell users when garment data is unavailable

For a significant fraction of products — especially on multi-brand marketplaces — finished garment measurements won’t be available. In this case, you’re back to brand-level size charts, and fabric-specific adjustments aren’t possible.

The honest approach: surface what you know and what you don’t.

We recommend size M based on your measurements. Note: we don't have specific 
measurements for this garment. If it contains stretch fabric, the fit may be 
more flexible than the size chart suggests. Check the product description for 
fabric composition.

This is more useful than a confident recommendation that doesn’t account for the garment’s actual properties.


Body dimension prediction solves one part of the sizing problem — the user’s body. The garment dimension data is the other part, and it’s the one that’s harder to standardize across a multi-brand catalog. The most accurate sizing systems combine both: a prediction API for user dimensions and a garment measurement database for product dimensions. Most systems start with the first and add the second over time as their catalog data matures.

Try DimensionsPot

Free tier — 100 requests/month, no credit card required.

Get API on RapidAPI