Positioning Flex Elements

Lecture notes: align-items, align-self, flex-wrap, order, flex-grow and other Flexbox properties

1. align-items — alignment along the cross axis

The align-items property is set on the flex container and controls the placement of items along the cross axis.

Value Behavior
flex-start Pin to the start of the cross axis
flex-end Pin to the end of the cross axis
center Center along the cross axis
baseline Align to the text baseline (useful when font-size differs)
stretch (default) Stretch items to the full height of the container
Remember: “vertical” and “horizontal” in Flexbox are relative. If flex-direction:
column
, the axes swap: the main axis runs top to bottom, and the cross axis runs left to right.

2. justify-content — alignment along the main axis

The justify-content property controls the distribution of items and free space along the main axis.

Value Behavior
flex-start (default) Pin to the start of the main axis
flex-end Pin to the end of the main axis
center Center the items
space-between Outer items pinned to the edges, free space distributed evenly between items
space-around Equal gaps around each item (outer gaps = half of the inner ones)
space-evenly All gaps are perfectly equal (both between items and at the edges)

Centering a modal window

.popup {
display: flex;
justify-content: center;  /* horizontally */
align-items: center;      /* vertically */
}

3. flex-shrink — shrink factor

The flex-shrink property determines whether an item inside a flex container can shrink when the screen size decreases.

Syntax

flex-shrink: 1;  /* default — the item shrinks */
flex-shrink: 0;  /* the item does NOT shrink */

The value is any positive number from 0 upward. The default is 1, meaning the item shrinks together with the container.

If you set 0, the item keeps its dimensions regardless of the screen width.

Practical example: a search bar

Imagine a search bar with three parts: a hint on the left, an input in the middle, and a “Search” button on the right. If you give all the items sizes in percentages, on small screens the hint will break onto extra lines and the button text will be clipped.

The solution: prevent the hint and the button from shrinking:

/* Hint and button — fixed */
.hint, .button {
flex-shrink: 0;
}
/* Input takes up the remaining space */
.search-input {
flex-grow: 1;
}

4. flex-grow — grow factor

The flex-grow property determines whether an item can grow to fill free space.

Syntax

flex-grow: 0;  /* default — does not grow */
flex-grow: 1;  /* grows, fills the free space */
flex-grow: 2;  /* takes twice as much as flex-grow: 1 */

Unlike flex-shrink, different flex-grow values really do produce different results. An item with flex-grow: 2 will take twice as much free space as an item with flex-grow:
1
.

Combining flex-shrink and flex-grow

For the search bar: the hint and the button neither shrink nor grow, while the input takes up all the free space:

.hint, .button {
flex-shrink: 0;
flex-grow: 0;
}
.search-input {
flex-grow: 1;
}

Now on any screen the left and right parts take up exactly as much room as their content needs, and the input fills the rest.

5. flex-basis and item sizing

The flex-basis property defines the initial size of an item in a flex container. It is the equivalent of width for horizontal flex containers and height for vertical ones.

Syntax

flex-basis: 250px;
flex-basis: 50%;
flex-basis: auto;  /* size based on content */

Priority

flex-basis is not a hard width but a maximum preferred size. If there isn’t enough room in the container, the items will shrink.

  • flex-basis takes precedence over width — if you set both, width is ignored
  • min-width / max-width take precedence over flex-basis

In a vertical flexbox

If you set flex-direction: column, then flex-basis defines the item’s height (instead of its width). Similarly, height is ignored, while min-height / max-height have higher priority.

Rule

Do not mix flex-basis with width / height. Use either flex-basis, or width (height) together with the min-/max- variants.

6. The flex shorthand

The flex-grow, flex-shrink, and flex-basis properties can be written in shorthand via flex:

flex: <flex-grow> <flex-shrink> <flex-basis>;

Notation options

Notation Equivalent Description
flex: auto flex: 1 1 auto Grows, shrinks, size based on content
flex: initial flex: 0 1 auto Default value: does not grow, shrinks
flex: none flex: 0 0 auto Does not grow, does not shrink — fixed size
flex: 1 flex: 1 1 0 Grows and shrinks proportionally
flex: 2 flex: 2 1 0 Takes twice as much space as flex: 1

The second value — a number or a size?

The browser figures it out automatically: if the second value is a plain number (1, 2, 3), it’s flex-shrink. If it’s a value with units (px, %, rem), it’s flex-basis:

flex: 0 auto;    /* flex-grow: 0, flex-basis: auto (flex-shrink: 1 by default) */
flex: 1 200px;   /* flex-grow: 1, flex-basis: 200px */

Simplifying the search bar

.hint, .button {
flex: none;   /* does not shrink, does not grow */
}
.search-input {
flex: 1;      /* takes up all the free space */
}

7. Distributing space via flex

Instead of percentages, you can use flex to distribute space among items. The numbers define the proportions:

/* Three columns: 20% + 30% + 50% */
.col-1 { flex: 2; }  /* 2/10 = 20% */
.col-2 { flex: 3; }  /* 3/10 = 30% */
.col-3 { flex: 5; }  /* 5/10 = 50% */

The sum of the flex values defines the “total number of parts.” Each item receives its share. For example, 2 + 3 + 5 = 10 parts, and the first item takes up 2/10 of the space.

Advantages over percentages

  • Adding new items — the space is redistributed automatically
  • The same flex: 1 for all — the items are always the same size
  • On mobile — you turn off display: flex, and the blocks become ordinary divs that stack one below another

Responsive column layout

.container {
display: flex;
}
.main { flex: 2; }   /* 2/3 of the space */
.sidebar { flex: 1; } /* 1/3 of the space */
@media (max-width: 768px) {
.container {
display: block; /* turn off flex — blocks stack one below another */
}
}

8. The order property

The order property changes the display order of items in a flex container without changing the HTML. It only works in flexbox.

Syntax

order: 0;   /* default */
order: 1;   /* display later */
order: -1;  /* display earlier */

The value is any integer (positive or negative). The smaller the number, the earlier the item appears:

  • In a horizontal flexbox: a smaller number is further left
  • In a vertical flexbox: a smaller number is higher up

Example: a news card

On desktop: image → heading → tags → text. On mobile, the designer wants the tags below the text. The solution is to add order via a media query:

.card {
display: flex;
flex-direction: column;
}
@media (max-width: 480px) {
.card-tags {
order: 1; /* 1 > 0, so the tags move down */
}
}

On desktop all the items have order: 0 and are displayed in HTML order. On mobile the tags get order: 1 and move down.

HTML semantics

You can check the semantics of your markup by disabling CSS in the browser. Without styles, the page should read logically: headings are headings, lists are lists (not divs with spans), navigation is <nav> with <ul>.

9. align-content — aligning the rows of a flex container

The align-content property controls the distribution of rows in a multi-row flex container along the cross axis (works only with flex-wrap: wrap).

Value Behavior
flex-start Rows pinned to the start
flex-end Rows pinned to the end
center Rows centered
space-between Outer rows pinned to the edges, space between rows even
space-around Equal gaps around each row
stretch (default) Rows stretch to the full height of the container

10. align-self — individual alignment of a flex item

The align-self property lets you override align-items for one specific flex item along the cross axis.

.container {
display: flex;
align-items: flex-start;
}
.button {
align-self: center;  /* Only this button is centered */
}
Value Behavior
auto (default) Inherits the container’s align-items value
flex-start Pins to the start of the cross axis
flex-end Pins to the end of the cross axis
center Centers along the cross axis
stretch Stretches to the full height of the row
baseline Aligns to the text baseline

Alternative: margin auto

You can also center a single item with margin-top: auto; margin-bottom: auto;, but align-self: center is a more explicit and semantic approach.

11. Centering items with margin: auto

In a flex container, margin: auto works both horizontally and vertically (unlike the normal flow, where margin-top: auto = 0).

.container {
display: flex;
width: 400px;
height: 400px;
}
.box {
width: 100px;
height: 100px;
margin: auto;  /* Centers both horizontally and vertically */
}

margin auto in flex — distributing items

Item 1 Item 2 Result
margin-left: auto The item is pushed to the right
margin-right: auto margin-left: auto The items move to opposite corners
margin-right: auto margin-right: auto Both are pushed to the left
margin-left: auto margin-left: auto Both are pushed to the right
margin: auto for both Both are centered
Comparison with justify-content: margin: auto controls individual items, whereas justify-content controls all the items in the container at once.

12. position: fixed — fixed positioning

position: fixed behaves almost like absolute, but with one key difference: the element stays fixed while scrolling.

What it shares with absolute

  • Width/height are calculated by content (not 100% of the parent)
  • The element is invisible to its siblings and parent
  • You can set width/height even on inline elements
  • Controlled via top, right, bottom, left

Difference from absolute

absolute fixed
Reference point The nearest parent with position: relative (or the viewport, if there is none) Always the viewport (the browser window)
On scroll Scrolls together with the page Stays in place
Responds to a relative parent Yes No

Typical examples of fixed

  • A fixed header — always at the top while scrolling
  • A modal window — covers the whole screen, doesn’t move
  • A “Back to top” button — always in the corner of the screen
  • A chatbot — a support window in the bottom right
  • A side menu (dashboard) — fixed navigation on the left
/* Modal window — fixed instead of absolute */
.popup {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 9999;          /* guaranteed on top of everything */
display: flex;
justify-content: center;
align-items: center;
}
A large z-index (9999) is used for modal windows to guarantee they cover all the other elements on the page — fixed headers, chatbots, and so on.

13. display: none — hiding completely

display: none removes the element from the page entirely — as if it had been deleted from the HTML.

Hiding method Visible? Takes up space? Interactive? Accessible to screen readers?
display: none No No No No
opacity: 0 No Yes Yes (can be clicked) Yes
Visual hiding (clip-path) No No Yes (Tab) Yes
When to use which:

  • display: none — the element should not exist on the page (a closed modal window, a hidden tab)
  • Visual hiding (clip-path) — the element is needed but not visible (text for screen readers, hidden labels)

14. Showing/hiding with classes (the popup pattern)

The classic approach for modal windows, dropdown menus, and tabs:

/* Base state — hidden */
.popup {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: none;          /* hidden */
}
/* Active state — shown */
.popup--active {
display: flex;           /* overrides display: none */
justify-content: center;
align-items: center;
}

How this works with JavaScript

// Close the popup when the close button is clicked
document.querySelector('.popup__close')
.addEventListener('click', function() {
document.querySelector('.popup--active')
.classList.remove('popup--active');
});

JavaScript only adds/removes a class. All the styling is in CSS.

Order matters! The .popup--active class must be lower in the CSS than .popup. With equal specificity, the browser applies whichever comes last.

15. Specificity of CSS selectors

When several rules with the same property apply to one element, the browser chooses based on the specificity value.

The formula: 4 numbers

Position What we count Example
A Inline style (style="...") 0 or 1
B Number of ids #header → 1
C Number of classes, pseudo-classes, attributes .nav:hover → 2
D Number of elements (tags), pseudo-elements div::before → 2

Calculation examples

Selector A B C D
span 0 0 0 1
.slogan 0 0 1 0
#slogan 0 1 0 0
style="..." 1 0 0 0
ul > .widget.socials 0 0 2 1
.widget.socials 0 0 2 0
div.widget:hover 0 0 2 1
These are 4 separate numbers, not one! 0,0,0,20 is still less than 0,0,1,0. A class selector is always more specific than any number of tags.

16. What does NOT affect specificity

  • The child combinator > — adds no weight
  • The adjacent sibling combinator + — adds no weight
  • The general sibling combinator ~ — adds no weight
  • The descendant combinator (space) — adds no weight
/* Both have a specificity of 0,0,2,1 */
ul > .widget.socials  { ... }
ul .widget.socials    { ... }
Counterintuitive: the child combinator > “narrows” the selection, but does not raise specificity.

17. Equal specificity → order in the CSS

If two selectors have equal specificity, the one located lower in the CSS file wins.

/* Specificity of both: 0,0,1,0 */
.slogan { font-size: 40px; }  /* ← loses */
.text   { font-size: 20px; }  /* ← wins */
The order of classes in the HTML doesn’t matter. It makes no difference whether you write class="slogan
text"
or class="text slogan". Only the order of the rules in the CSS matters.

Practical application

That’s why third-party styles (libraries, widgets) are linked before your own styles:

<!-- 1. First — third-party styles -->
<link rel="stylesheet" href="widget.css">
<!-- 2. Then — your styles -->
<link rel="stylesheet" href="style.css">

Thanks to this, your selector with the same specificity will override the library’s styles.

18. The child combinator > and combining with a tag

Descendant vs child

Selector What it selects
.widget div All divs inside .widget (at any nesting level)
.widget > div Only the direct child divs (the first level)

Combining a class with a tag

/* Any element with the class .card */
.card { ... }
/* Only <article> with the class .card */
article.card { ... }
Avoid binding to a tag! The selector div.card rigidly binds the styles to <div>. If you later change the tag to <article>, the styles will break. Style by classes.

19. !important — when there are no other options

!important raises the priority of a specific property (not the whole selector) above inline styles:

span {
font-size: 10px !important;  /* beats even style="font-size: 20px" */
}

If there are two !important declarations, the one with the higher selector specificity wins.

!important is an “anti-pattern.” It’s a sign of a flaw in your CSS architecture. It’s very hard to “dig out” of the code later.

  • Don’t use it unless absolutely necessary
  • If you did use it — always leave a comment explaining why
  • Acceptable cases: a quick hotfix, overriding a third-party widget without access to its CSS

20. CSS architecture recommendations

  • Style by classes, not by id (id is for JavaScript)
  • As flat a structure as possible: one class → one selector (.popup-box, .popup-close)
  • Avoid deep nesting: .page .main .content h1 is bad
  • Better: .main-title — simple, clear, low specificity
  • Link third-party libraries before your own styles
  • Don’t use !important in ordinary work
The BEM approach (Block Element Modifier) helps keep specificity flat: .popup, .popup__box, .popup--active all have a specificity of 0,0,1,0.

21. Loading fonts — @font-face

The @font-face construct describes a font file for the browser. Each typeface style gets its own @font-face.

/* Regular style */
@font-face {
font-family: "PT Sans";
src: url("../fonts/pt-sans-regular.woff2") format("woff2");
font-weight: 400;
font-style: normal;
}
/* Bold style */
@font-face {
font-family: "PT Sans";
src: url("../fonts/pt-sans-bold.woff2") format("woff2");
font-weight: 700;
font-style: normal;
}

How the browser chooses a file

The browser compares three of the element’s parameters with the description in @font-face:

  1. font-family — does it match?
  2. font-weight — does it match?
  3. font-style — does it match?

If all three match, the corresponding font file is loaded.

Fallback font (font stack)

body {
font-family: "PT Sans", Arial, sans-serif;
}
Always specify a fallback font: font name → system font (Arial, Georgia) → generic family (sans-serif or serif).
Family Description Example
sans-serif Without serifs (grotesque) Arial, Helvetica
serif With serifs (antiqua) Times New Roman, Georgia

22. Reading text parameters from a layout

In Photoshop/Figma, for each text layer we read:

Parameter CSS property Note
Font family font-family PT Sans, Roboto, etc.
Style (Bold, Regular…) font-weight 400 = Regular, 700 = Bold
Font size font-size Make sure the units are pixels
Line height line-height If “Auto” → normal
Uppercase icon text-transform: uppercase
Color color Eyedropper or the layer’s properties panel
Single-line text: don’t copy the line-height for single-line headings! Designers often use line height for spacing. If the text becomes two lines, the line spacing will be too large. Set line-height: normal or pick a sensible value.

23. Image formats

Format Type Transparency Compression Used for
JPEG Raster No Lossy Photos, backgrounds, illustrations
PNG Raster Yes Lossless Logos, elements with transparency
SVG Vector Yes Minimal size Icons, graphics, simple illustrations
WebP Raster Yes Better than JPEG/PNG A modern alternative to JPEG and PNG
WebP is a modern format from Google. Supported by all browsers since 2020. Smaller file size at the same quality.

24. Summary table

Topic Key point
align-items Alignment along the cross axis: flex-start, center, flex-end, baseline, stretch
justify-content Alignment along the main axis: center, space-between, space-around, space-evenly
flex-shrink Shrink factor: 1 (default) — shrinks, 0 — doesn’t
flex-grow Grow factor: 0 (default), 1+ — fills the free space
flex-basis Initial item size; takes precedence over width/height
flex (shorthand) flex: none — fixed; flex: 1 — fills the space; flex: auto — grows to fit content
Distributing space flex numbers define the proportions: flex: 2 + flex: 1 = 2/3 + 1/3
order Change the display order without changing the HTML; a smaller number is earlier
align-content Aligns rows in a multi-row flex container (flex-wrap: wrap)
align-self Individual alignment of a flex item; overrides the container’s align-items
margin: auto in flex Centers an item both horizontally and vertically; controls individual items
position: fixed Like absolute, but stays fixed while scrolling; always relative to the viewport
display: none Hides completely; the element “doesn’t exist” (takes no space, not interactive)
Popup pattern .popup (display: none) + .popup--active (display:
flex
); JS adds/removes the class
Specificity 4 numbers: inline / id / classes+pseudo-classes / tags+pseudo-elements
Equal specificity The rule placed lower in the CSS wins
!important Raises the priority of a single property; an anti-pattern, avoid it
The > selector Child (first level); does not affect specificity
@font-face Describes a font file; one @font-face = one typeface style
font stack Always: custom → system → sans-serif/serif
Image formats JPEG — photos; PNG — transparency; SVG — icons; WebP — a modern alternative

Vitalii Kaplia

Founder, Web Developer & WordPress Expert

I became interested in programming back in 1997. The first acquaintance with a future profession was using Visual Basic. In…

More about author

A digital product engineer and web solutions architect

Free consultation + cost calculation

Let’s discuss your project?

Free consultation + cost calculation

More interesting articles

Customer login

This site uses cookies

We use cookies to personalize content and ads, provide social media features, and analyze our traffic. We also share information about your use of our website with our social media, advertising, and analytics partners, who may combine it with other information you have provided to them or collected when you use their services. By continuing to use our site, you consent to our use of cookies and accept our Privacy Policy and Terms of Use.

Virtual assistant
Hi! I'm the KAPLIA.PRO virtual assistant! I can tell you about our services, portfolio projects, ballpark pricing, and how we work — from websites and eCommerce to web apps, CRMs, bots, and AI agents. Ask away!

By continuing with the AI assistant, I agree to the site’s terms of use and privacy policy.

AI assistant may make mistakes in responses