\n\n\n\n.toolbar {\n display: flex;\n flex-wrap: wrap; / lets the row break instead of shrinking the buttons when they grow /\n gap: 4px;\n width: 300px;\n margin: 16px;\n padding: 0;\n}\n.toolbar button {\n box-sizing: border-box;\n width: 28px;\n height: 28px;\n padding: 0;\n border: 1px solid #667;\n border-radius: 4px;\n background: #eef0f6;\n}\n\n/ Primary input is a finger: same markup, bigger boxes. /\n@media (pointer: coarse) {\n .toolbar button {\n width: 44px;\n height: 44px;\n }\n}\n\nThe desktop rules are untouched: 28px buttons with a 4px gap.\nThe coarse block raises width and height to 44px. Because the buttons are real boxes of that size, the whole 44px square is the target and no extra hit-area trick is needed.\nThe toolbar is 300px wide. At 44px with 4px gaps, 6 x 44 + 5 x 4 = 284px fits and 7 x 44 + 6 x 4 = 332px does not, so the eight buttons break into rows of 6 and 2. On a fine pointer, 8 x 28 + 7 x 4 = 252px fits in one row.\nWhere wrapping would make the toolbar too tall (a 14-button toolbar at 44px wraps to three rows of 6, 6 and 2, as the last line of the output shows), the alternatives are horizontal scrolling or moving the least-used actions into an overflow menu. Those change the markup and behaviour, which is the point at which \"no redesign\" stops being possible.\n\nVerifying it\n\nThe test runs in Chromium, Firefox and WebKit, the three browser engines (the rendering cores that lay out the page), driven by Playwright 1.48.2, a library that scripts real browsers; its WebKit build is Playwright's, not Safari, and it runs headless, meaning without a visible window, so it can measure layout and simulate a tap but cannot tell how a real thumb feels on a real phone. A fine pointer is the default context. A touch context is created with hasTouch: true, in which matchMedia('(pointer: coarse)') is true in all three engines. It asserts the sizes, the row counts, that nothing pokes out of the toolbar, and that a real touch tap 40px right and 20px down from the first button's corner (inside a 44px box, outside a 28px one) activates it. Deleting the coarse rule or the flex-wrap declaration makes the assertions fail; both mutants fail the 44px size assertion, the second because a non-wrapping flex row shrinks its items to fit instead of letting them overflow.\n\n// check.mjs\nimport { chromium, firefox, webkit } from 'playwright';\nimport { readFileSync } from 'node:fs';\n\nconst css = readFileSync('toolbar.css', 'utf8');\nconst html = readFileSync('index.html', 'utf8');\nconst variants = {\n shipped: css,\n noCoarseRule: css.replace(/@media \\(pointer: coarse\\) \\{[\\s\\S]*\\n\\}\\n/, ''),\n noWrap: css.replace('flex-wrap: wrap;', 'flex-wrap: nowrap;'),\n};\nconst ok = (c, m) => { if (!c) throw new Error('ASSERT FAILED: ' + m); };\n\nasync function open(browser, variant, touch) {\n const ctx = await browser.newContext({ viewport: { width: 400, height: 400 }, hasTouch: touch });\n const p = await ctx.newPage();\n await p.route('**/toolbar.css', r => r.fulfill({ contentType: 'text/css', body: variants[variant] }));\n await p.route('**/index.html', r => r.fulfill({ contentType: 'text/html', body: html }));\n await p.goto('http://x.test/index.html');\n return p;\n}\nconst layout = p => p.evaluate(() => {\n const bar = document.querySelector('.toolbar');\n const r = [...bar.querySelectorAll('button')].map(b => b.getBoundingClientRect());\n const rows = {};\n r.forEach(b => { rows[Math.round(b.top)] = (rows[Math.round(b.top)] || 0) + 1; });\n return {\n coarse: matchMedia('(pointer: coarse)').matches,\n size: [r[0].width, r[0].height],\n perRow: Object.values(rows),\n overflowsBar: r.some(b => b.right > bar.getBoundingClientRect().right + 0.5),\n minSide: Math.min(...r.map(b => Math.min(b.width, b.height))),\n };\n});\n\nasync function fineTest(b) {\n const p = await open(b, 'shipped', false);\n const m = await layout(p);\n ok(!m.coarse && m.size.join() === '28,28' && m.perRow.join() === '8', 'fine pointer keeps the dense 28px single row');\n return m;\n}\nasync function coarseTest(b, variant) {\n const p = await open(b, variant, true);\n const m = await layout(p);\n ok(m.coarse, 'touch context reports pointer: coarse');\n ok(m.minSide >= 44, 'every button is at least 44 by 44');\n ok(!m.overflowsBar, 'no button pokes out of the toolbar');\n ok(m.perRow.join() === '6,2', 'wraps to rows of 6 and 2');\n // a tap 40px right and 20px down from a button's top-left lands inside its 44px box but outside a 28px one\n const first = await p.evaluate(() => { const r = document.querySelector('.toolbar button').getBoundingClientRect(); return { x: r.x, y: r.y }; });\n await p.touchscreen.tap(first.x + 40, first.y + 20);\n ok((await p.evaluate(() => window.clicks)).join() === 'Bold', 'tap near the edge of the 44px button activates it');\n return m;\n}\n\nfor (const [name, type] of [['chromium', chromium], ['firefox', firefox], ['webkit', webkit]]) {\n const b = await type.launch();\n const f = await fineTest(b);\n const c = await coarseTest(b, 'shipped');\n console.log(name, 'fine:', JSON.stringify({ size: f.size, perRow: f.perRow }), 'coarse:', JSON.stringify({ size: c.size, perRow: c.perRow }));\n const res = {};\n for (const v of ['noCoarseRule', 'noWrap']) { try { await coarseTest(b, v); res[v] = 'STILL PASSES'; } catch (e) { res[v] = 'fails: ' + e.message; } }\n console.log(' without the rule:', JSON.stringify(res));\n // 14 buttons: clone the first button until there are 14, then count buttons per row at 44px\n const p14 = await open(b, 'shipped', true);\n await p14.evaluate(() => { const bar = document.querySelector('.toolbar'); while (bar.children.length < 14) bar.append(bar.firstElementChild.cloneNode(true)); });\n const m14 = await layout(p14);\n ok(m14.perRow.join() === '6,6,2', '14 buttons wrap to rows of 6, 6 and 2');\n console.log(' 14 buttons, coarse pointer, buttons per row:', JSON.stringify(m14.perRow));\n await b.close();\n}\n\nRun in the Playwright 1.48.2 container, it prints the same values for all three engines (repeated runs print the same thing):\n\nchromium fine: {\"size\":[28,28],\"perRow\":[8]} coarse: {\"size\":[44,44],\"perRow\":[6,2]}\n without the rule: {\"noCoarseRule\":\"fails: ASSERT FAILED: every button is at least 44 by 44\",\"noWrap\":\"fails: ASSERT FAILED: every button is at least 44 by 44\"}\n 14 buttons, coarse pointer, buttons per row: [6,6,2]\nfirefox fine: {\"size\":[28,28],\"perRow\":[8]} coarse: {\"size\":[44,44],\"perRow\":[6,2]}\n without the rule: {\"noCoarseRule\":\"fails: ASSERT FAILED: every button is at least 44 by 44\",\"noWrap\":\"fails: ASSERT FAILED: every button is at least 44 by 44\"}\n 14 buttons, coarse pointer, buttons per row: [6,6,2]\nwebkit fine: {\"size\":[28,28],\"perRow\":[8]} coarse: {\"size\":[44,44],\"perRow\":[6,2]}\n without the rule: {\"noCoarseRule\":\"fails: ASSERT FAILED: every button is at least 44 by 44\",\"noWrap\":\"fails: ASSERT FAILED: every button is at least 44 by 44\"}\n 14 buttons, coarse pointer, buttons per row: [6,6,2]\n\nHow to read it: size is the first button's width and height in CSS pixels; perRow lists how many buttons sit on each row, found by grouping the buttons by the rounded top coordinate of their boxes (getBoundingClientRect() returns a box's position and size), so [6,2] means a row of six and a row of two. In layout(), overflowsBar is true if any button's right edge passes the toolbar's right edge and minSide is the smallest side of any button. fineTest opens a normal (mouse-like) page and expects the dense single row; coarseTest opens a touch page and expects the 44px, two-row result plus the tap. without the rule reruns the touch checks against a stylesheet with the coarse block deleted or with flex-wrap switched off, and fails: followed by the assertion message means the checks caught the missing rule (both mutants trip the 44px size assertion first). The last line adds six more buttons (14 in all) and counts rows again.\n\nComplexity and edge cases\n\nThe layout is a single flex pass over eight items. Edge cases to handle:\n\nHybrid devices (laptops or tablets that have both a touchscreen and a mouse or trackpad): pointer reports only the primary input (see the MDN definition above), so a touch laptop whose primary input is the trackpad keeps the dense toolbar; any-pointer is true if any attached input matches, so switch to it if that matters.\nLabels: the buttons carry aria-label so the accessible name does not depend on the glyph; resizing them does not change it.\nPage height: wrapping makes the toolbar taller on touch, which pushes content below it down; account for that in the surrounding layout.\nZoom and user font size: the sizes are in CSS pixels, so they track browser zoom. If the buttons are sized in rem instead, they also track the user's default font size.\n\nRunning the code\n\nmkdir demo && cd demo\necho '{\"type\":\"module\"}' > package.json\nnpm i playwright@1.48.2 && npx playwright install chromium firefox webkit\nsave the three listings above as index.html, toolbar.css and check.mjs, then:\nnode check.mjs"}}]}

Mid-Level UI Designer Interview Preparation Guide - FAANG Standards

UI Designer
Mid Level
7 rounds
Updated 6/17/2026

This guide is based on general FAANG interview practices and may not reflect specific company procedures.

FAANG companies conducting mid-level UI Designer interviews typically follow a structured process spanning 4-6 weeks. The process begins with recruiter screening to verify background and role fit, followed by portfolio and design background evaluation. Technical assessments include practical design challenges and design systems expertise. Behavioral rounds assess collaboration, communication, and cross-functional impact. A final hiring manager round determines fit and growth trajectory. Throughout, candidates are evaluated on design execution, design thinking, communication clarity, and ability to influence and collaborate with engineers and product teams.

Interview Rounds

1

Recruiter Phone Screen

2

Portfolio Review and Design Background

3

Design Challenge - Practical Design Task

4

Design Systems and Advanced Design Topics

5

Collaboration, Communication, and Design Influence

6

Design Thinking and Product Understanding

7

Hiring Manager Round - Vision and Culture Fit

Frequently Asked UI Designer Interview Questions

Mentoring and CoachingMediumBehavioral
67 practiced

Walk me through a time you helped someone develop a skill that doesn't come naturally to you, or one you had to learn how to teach as you went.

Prioritization and Trade-Off DecisionsMediumTechnical
124 practiced

You have six weeks and a small budget to ship an MVP of a social app. How do you decide which features are in and out, what do you cut first if the schedule slips, and how do you explain the cuts?

Visual Design Fundamentals: Typography, Color, and BrandMediumTechnical
81 practiced

A screen has a handful of loosely related controls and content blocks scattered across it, and users keep asking support which button goes with which section. What visual-grouping principles would you apply to make those relationships obvious without adding a single label, and how would you apply them here?

Design Systems and Component LibrariesMediumTechnical
36 practiced

Design a reusable Button component API in React using TypeScript. Describe the full prop shape you'd design, including how you'd let consumers render the button as a different underlying element (for example a link) without duplicating the component. Also describe how you'd let a parent component get a direct reference to the underlying DOM node, and how you'd ensure keyboard and screen reader accessibility.

Design Metrics and Impact MeasurementEasyTechnical
23 practiced

For a messaging app feature, propose 4 KPIs to measure feature adoption and early retention. For each KPI specify the event or metric definition (e.g., 'used feature X at least once in first week'), why it's useful, and one potential confounding factor to watch.

Career Goals and ProgressionEasyBehavioral
66 practiced

Tell me about a short-term project you volunteered for specifically to accelerate your growth. Why that project, and what did it actually change about your trajectory?

Design Thinking and the End-to-End Design ProcessHardTechnical
45 practiced

You have several validated concepts for a complex feature and a limited research budget to pick one. Walk me through how you would structure that decision: which criteria you would weigh and why, how you would score the options against them, and what you do when two options effectively tie.

Cross-Functional CollaborationMediumTechnical
29 practiced

Design or product wants to ship a change that should improve a key business metric, but you're not confident it won't hurt the user experience in ways that metric won't catch. How do you work with design and product to validate the idea before committing to it?

Problem Definition and FramingMediumTechnical
70 practiced

You are handed the ambiguous brief 'make checkout less confusing.' Produce a two sentence problem statement, three prioritized research questions that would reduce the most uncertainty, and two prototype experiments to validate improvements, including a measurable outcome for each experiment.

Frontend Fundamentals: HTML, CSS, and Responsive StylingEasyTechnical
116 practiced

What size should touch targets be on mobile, and why? How would you keep a dense desktop toolbar usable on touch screens without redesigning it?

Additional Information

Want to create your own tailored preparation guide using our deep research?

Get Started for Free

Interview-Ready Courses

Visual-first, interactive, structured learning paths

Browse UI Designer jobs

AI-enriched listings across hundreds of company career pages

Explore Jobs