Container queries: prefer the right container-type for the axis you query

Container queries: prefer the right container-type for the axis you query

calendar_today ago • schedule1 min read
— Originally published at chriseugenerodriguez.com

Prerequisites

  • Basic familiarity with CSS container queries and the container-type and container-name properties.
  • Ability to inspect DOM and computed styles in the browser devtools.

Implementation decision

  • If your rules include block-axis queries (height, block-size), keep the container that those elements rely on set to container-type: size.
  • If you only need inline-axis checks (width), prefer container-type: inline-size to limit containment cost.
  • Use container-name to ensure the browser targets the intended ancestor when nested containers could confuse matching.

Expected result

  • When the container remains container-type: size, both width- and height-based @container queries will find a valid ancestor and evaluate normally.
  • If you switch the same container to container-type: inline-size at runtime, inline-axis (width) queries will still match, but block-axis (height) queries will report no eligible container and stop matching.
  • A named container still resolves by name, but a name does not grant missing axis support; axis-based queries still need the right container-type.

Limitation

  • The guidance isolates containment eligibility. It does not cover cases where a query fails due to selector specificity, layout overrides, or DOM moves that change ancestors. Always verify the actual DOM path and computed container-type in the browser where the issue appears.

Working example

export function createElement({ tag = 'div', width = 0, height = 0 } = {}) {
  return {
    tag,
    width,
    height,
    parent: null,
    children: [],
    containerType: 'normal',
    containerName: undefined,
  };
}

export function appendChild(parent, child) {
  child.parent = parent;
  parent.children.push(child);
}

export function setContainerType(el, type) {
  el.containerType = type;
}

export function setContainerName(el, name) {
  el.containerName = name;
}

export function toggleContainerType(el, nextType) {
  setContainerType(el, nextType);
}

function compare(op, left, right) {
  switch (op) {
    case '>': return left > right;
    case '>=': return left >= right;
    case '<': return left < right;
    case '<=': return left <= right;
    default: throw new Error(`unsupported compare operator: ${op}`);
  }
}

function queryAxis(query) {
  if (query.kind === 'name-only') return null;
  if (query.axis) return query.axis;
  if (query.feature === 'width') return 'inline';
  if (query.feature === 'height') return 'block';
  return null;
}

export function findEligibleContainer(startEl, query) {
  let node = startEl.parent;
  const axis = queryAxis(query);

  while (node) {
    if (query.kind === 'name-only') {
      if (node.containerName === query.name) return node;
    } else if (axis) {
      if (node.containerType === 'size') return node;
      if (node.containerType === 'inline-size' && axis === 'inline') return node;
    }
    node = node.parent;
  }

  return null;
}

export function evaluateQuery(targetEl, query) {
  const container = findEligibleContainer(targetEl, query);
  if (!container) {
    return { matched: false, reason: 'no-eligible-container', container: null };
  }

  if (query.kind === 'name-only') {
    return { matched: true, container };
  }

  const axis = queryAxis(query);
  const size = axis === 'inline' ? container.width : container.height;
  return {
    matched: compare(query.compare, size, query.value),
    container,
    containerValue: size,
  };
}

Read the full article: https://chriseugenerodriguez.com/blog/why-do-container-queries-stop-matching-when-you-switch-container-type-dynamically

🔥 Join developers growing publicly
Share your knowledge, build in public, and grow your developer presence with a global community.

More Posts

Your Backup Data Knows More Than You Think. HYCU aiR Is Finally Asking It the Right Questions.

Tom Smithverified - May 14

Tuesday Coding Tip 02 - Template with type-specific API

Jakub Neruda - Mar 10

Tailwind CSS for Beginners: From Zero to Your First Component

muhammadfarhan.dev - Jul 21

Optimizing the Clinical Interface: Data Management for Efficient Medical Outcomes

Huifer - Jan 26

Cisco's Amy Chang: A Model's "Passport" Doesn't Tell You Where It Actually Came From

Tom Smithverified - Aug 27
chevron_left
240 Points • 9 Badges
Santa Monica, CA • chriseugenerodriguez.com
6Posts
0Comments
1Connections
10 years fe

Related Jobs

View all jobs →

Commenters (This Week)

1 comment
1 comment

Contribute meaningful comments to climb the leaderboard and earn badges!