On this page

Appearance

Open Appearance in the navbar to choose White, Light, Dark or Black. Light is the initial view. The selection applies across every demo page and this guide; football attribute bands, ratings and results keep the same meanings in each appearance.

Four appearances, one database

White

White canvas and masthead, neutral light panels.

data-theme="white"
Light

Neutral grey canvas, light grey panels, near-black text and a navy masthead.

data-theme="light"
Dark

Dark slate canvas, navy panels and masthead.

data-theme="dark"
Black

True black canvas and masthead, charcoal panels.

data-theme="black"
<html data-theme="light">
<!-- Choose white, light, dark or black. -->

Compact layout is available in every appearance

Use the separate compact-layout control in the navbar to tighten headers, panel spacing and data rows. Changing appearance keeps the selected layout and every record in place.

<html data-theme="black" data-density="compact">
<!-- Omit data-density for the comfortable layout. -->

Tokens

Every component reads from tokens.css. V4 provides four appearances through data-theme="white", data-theme="light", data-theme="dark" and data-theme="black". Choose Appearance in the navbar to inspect each palette. Values shown are resolved live from the current theme.

Masthead

--color-masthead
--color-masthead-raised
--color-masthead-ink
--color-masthead-muted
--color-masthead-border

Surfaces

--color-canvas
--color-surface
--color-surface-raised
--color-surface-sunken
--color-surface-hover
--color-surface-overlay
--color-surface-inverse

Ink

--color-text
--color-text-secondary
--color-text-muted
--color-text-faint
--color-text-inverse
--color-text-on-accent

Borders and accent

--color-border
--color-border-strong
--color-border-subtle
--color-accent
--color-accent-hover
--color-accent-soft
--color-accent-ring

Meaning

--color-success
--color-success-soft
--color-warning
--color-warning-soft
--color-danger
--color-danger-soft
--color-info
--color-info-soft
--color-special
--color-special-soft

Attribute bands

--color-attr-low
--color-attr-mid
--color-attr-good
--color-attr-elite
--color-attr-bar-track
--color-attr-bar-low
--color-attr-bar-mid
--color-attr-bar-good
--color-attr-bar-elite

Pitch, stars, results

--color-pitch
--color-pitch-pos-natural
--color-pitch-pos-accomplished
--color-pitch-pos-competent
--color-pitch-pos-unconvincing
--color-pitch-pos-awkward
--color-star
--color-star-empty
--color-result-win
--color-result-draw
--color-result-loss

Spacing scale, 4px base

--space-1
--space-2
--space-3
--space-4
--space-5
--space-6
--space-7
--space-8
--space-9
--space-10
--space-11
--space-12

Type scale. Barlow for text and data, Barlow Semi Condensed for display

--text-2xsColumn headers, badges, notes
--text-xsDense table cells and captions
--text-smTable default and form controls
--text-mdBody text at 15px
--text-lgCard names and emphasis
--text-xlPanel-level headings
--text-2xlSection headings
--text-3xlPage titles
--text-4xlEntity names
--text-5xlSquad number tile

Radii

none
sm
md
lg
xl
pill

Shadows. Reserved for menus, dialogs and other floating surfaces

sm
md
lg
focus

Z-index ladder

--z-below-1
--z-base0
--z-raised10
--z-dropdown100
--z-sticky200
--z-sidebar300
--z-overlay400
--z-modal500
--z-toast600
--z-tooltip700

Motion

--duration-fast120ms
--duration-base180ms
--duration-slow320ms
--ease-standardcubic-bezier(0.2, 0, 0, 1)
--ease-outcubic-bezier(0, 0, 0.2, 1)
--ease-incubic-bezier(0.4, 0, 1, 1)
prefers-reduced-motionevery duration collapses to 0ms

Typography

One family in two widths. Barlow carries the interface and tabular numbers; Barlow Semi Condensed gives player names and display headings a football identity. Light uses near-black ink with medium-weight (500) body text, fact labels and fact notes, semibold (600) fact values and bold (700) headings. Other appearances retain their original type weights. Panel titles and labels use sentence case, aligned left so long pages are easy to scan.

Headings use the display face

Heading one, the page title

Heading two, a section

Heading three, a panel

Heading four

Prose and inline elements

Body text is Barlow at 15px with tabular numerals on by default, so 1,192 and 1,435 line up in a column. Links look like this, code like player_position, a key like /, and AM (R) carries its expansion in a title.

A note is the small muted copy under a table or panel that says where a figure comes from. It keeps to a readable measure.

Points are stored as applied, including real deductions. Deriving W×3+D contradicts the historical record.

Blanks and money

A value the version does not record is —, never 0. A money figure is rendered in GBP and rewritten client-side: £300,000. Change the currency in the navbar to see it convert.

<span class="blank" aria-label="not recorded">—</span>
<span class="money" data-gbp="300000">£300,000</span>

Layout primitives

Layout owns the space between things; components own their insides. The app shell (.app, .navbar, .sidebar, .app__main) is what this page is rendered in.

Stack: vertical rhythm

one
two
three
<div class="stack stack--sm">…</div>  <!-- --xs --sm --md --lg --xl -->

Cluster: inline items that wrap

Premier League
Sky Bet Championship
League One
League Two
National League
<div class="cluster cluster--between">…</div>

Grid: auto-fit columns

A
B
C
D
E
F
<div class="grid grid--min-sm">…</div>  <!-- or grid--2 / --3 / --4 -->

Panel grid: 12 columns behind every entity page

span 4
span 4
span 4
span 12
<div class="panel-grid">
  <section class="card panel-grid__item--span-4">…</section>
  <section class="card panel-grid__item--span-8">…</section>
</div>

With-sidebar: content beside an aside, wrapping when narrow

sidebar 18rem
content
<div class="with-sidebar with-sidebar--right">…</div>

Container and center

container--prose keeps a 68ch measure

Buttons

One primary action per view, inverted like the game's own Continue button. Everything else is bordered, ghost or a link. Focus shows the blue ring on every variant.

Variants

<button class="btn btn--primary" type="button">Continue</button>

Sizes

States: hover and focus are live; disabled and loading are shown

<button class="btn is-loading" aria-busy="true"><span>Saving</span></button>

With icons, icon only, block

Button group and pressed state

<div class="btn-group" role="group">
  <button class="btn btn--sm" aria-pressed="true">Dense</button>
  <button class="btn btn--sm" aria-pressed="false">Normal</button>
</div>

Inputs

Sunken fields on the panel surface, brightening to the surface colour on focus. Invalid fields go red on the border only; the message beside them does the explaining.

Sizes

<input class="input" type="text" placeholder="Name starts with">

States

Types

Input groups

£per week
<div class="input-group input-group--search">
  <svg class="input-group__icon">…</svg>
  <input class="input" type="search">
</div>

Selects

Native selects in a wrapper that draws the chevron, so the dropdown itself stays the platform one and works everywhere.

Sizes

<div class="select">
  <select class="select__control">…</select>
</div>

States

Inline and multiple

Checkboxes

Drawn with appearance: none on the input itself so the state lives on the real control; the label wraps it for a large hit target.

States

<label class="checkbox">
  <input class="checkbox__input" type="checkbox" checked>
  <span class="checkbox__label">Only current spells</span>
</label>

Small and inline

Radios

Same construction as checkboxes with a round control. Radio cards make the whole tile the target when the choices carry a description.

List

<label class="radio">
  <input class="radio__input" type="radio" name="feet" checked>
  <span class="radio__label">Both feet</span>
</label>

Inline and small

Radio cards

<label class="radio-card">
  <input class="radio__input" type="radio" name="version" checked>
  <span class="radio-card__body"><span class="radio-card__title">FM26 Update</span>…</span>
</label>

Toggles

A switch is a checkbox with role="switch". The on state uses the success green because a switch always answers a yes/no question. The segmented control is a radio group for two to four short choices.

States

<label class="toggle">
  <input class="toggle__input" type="checkbox" role="switch" checked>
  <span class="toggle__label">Show attribute bars</span>
</label>

Small and label first

Segmented control

<div class="segmented" role="radiogroup">
  <label class="segmented__option"><input class="segmented__input" type="radio" name="d" checked><span class="segmented__label">Dense</span></label>
</div>

Textareas

Vertical resize only, so a long note never breaks the panel width.

Sizes

<textarea class="textarea" rows="4"></textarea>

States

With a character count

Form groups and validation

A group is a label, an optional hint, the control and a message, wired together with aria-describedby. The error says what went wrong and how to fix it; it never apologises.

Label, hint, control

Case-insensitive prefix match on the person's full name.

Enter a four-digit year. 2020 means the 2019–20 season.

Matches England.

Not filterable: the column is not indexed.

<div class="form-group form-group--invalid">
  <label class="form-group__label" for="year">Season end year</label>
  <input class="input" id="year" aria-invalid="true" aria-describedby="year-error">
  <p class="form-group__error" id="year-error">Enter a four-digit year.</p>
</div>

Inline label, row of groups, fieldset

Feet

Inline filter bar, as used on the index pages

<form class="form-inline">
  <div class="form-group">…</div>
  <div class="form-group form-group--auto"><button class="btn btn--primary">Filter</button></div>
</form>

Cards

Panels adapt to the selected appearance and sit apart with 20px gaps. Modest 8px corners soften the frame; clear headings and comfortable data rows establish the hierarchy. Compact layout reduces header sizes, panel spacing and row height while keeping every value available.

Default panel, header with actions, footer

Personal information

Panel content. Sentence-case titles align left, with actions alongside and enough room for long names.

Season records

Panel content. Sentence-case titles align left, with actions alongside and enough room for long names.

With footer

Body
<section class="card">
  <header class="card__header"><h2 class="card__title">Personal information</h2></header>
  <div class="card__body">…</div>
  <footer class="card__footer">…</footer>
</section>

Variants

Flat

Panel content. Sentence-case titles align left, with actions alongside and enough room for long names.

Raised

Panel content. Sentence-case titles align left, with actions alongside and enough room for long names.

Outlined

Panel content. Sentence-case titles align left, with actions alongside and enough room for long names.

Sunken

Panel content. Sentence-case titles align left, with actions alongside and enough room for long names.

Accent rule in a club colour

Panel content. Sentence-case titles align left, with actions alongside and enough room for long names.

Interactive

Flush body for tables and facts, subtitle columns

Flush body

Founded
1886
Reputation
8650

Two bodies

Technical

First body
Second body, divided by a hairline

Collapsible panel (a details element)

Open by default
Click the header to collapse. Works without JavaScript.
Collapsed
Hidden until opened.
<details class="card card--collapsible" open>
  <summary class="card__header"><span class="card__title">Injuries</span></summary>
  <div class="card__body">…</div>
</details>

Card list and browse card

Card list

  • Row one
  • Row two
  • Row three
Players157,940

Badges, tags, results

A badge names a status or a category; colour is reserved for meaning. Tags are the two- or three-letter chips the game prints beside a player. Results are the W/D/L squares.

Badges

NeutralSuccessWarningDangerInfoSpecial
<span class="badge badge--success">Active</span>

Solid and outline

SolidSuccessWarningDangerInfoSpecial
OutlineSuccessDanger

Sizes, dot, count

SmallDefaultLargeCurrentInjuries83

Tags: the game's short status chips

UnkSptWntIntYthInjUnrLon
<span class="tag tag--danger" title="Injured">Inj</span>

Results, codes, swatches

WWDL–ENGPL Foreground #310039
<span class="result result--win">W</span>
<span class="swatch" style="--swatch: #E20613"></span>

Alerts

An alert stays on the page and explains something about the data in front of the reader. The left rule carries the meaning; the icon and the words carry it too, so colour is never the only signal.

Variants

Points are stored as applied

Deductions are in the record. Nothing on this page is recomputed from results.

Currency set to Euro

Figures are converted in your browser from the stored GBP values.

Position competency is incomplete in this version

The four CM databases carry competency only for GK and SW. This is a decoder gap, not absent data.

This page could not be loaded

The version database did not answer in time. Try again in a moment.

Only 150 people carry a staff record

Managers who used to be players are stored as players. Build a staff list from staff_history, never from the staff table.

<div class="alert alert--warning" role="status">
  <svg class="alert__icon">…</svg>
  <div class="alert__content">
    <p class="alert__title">Title</p>
    <p class="alert__body">What happened and what to do.</p>
  </div>
  <button class="alert__close" aria-label="Dismiss">×</button>
</div>

Compact and bare, with actions

Page 400 is the deepest this list serves. Narrow the filter to reach later rows.

Toasts

A toast confirms something that just happened and goes away. Hovering pauses the timer; a danger toast uses role="alert". Motion respects reduced-motion.

Static examples (shown inline; live toasts stack bottom-right)

Choose your theme

Open Appearance in the navbar. Your preference is saved.

Currency set to Euro

Remembered in this browser.

Slow connection

The page is still loading.

Could not load the squad

Retry in a moment.

FMDB.toast({ variant: "success", title: "Currency set to Euro", body: "Remembered in this browser.", duration: 4000 });

Trigger live toasts

Modals

Built on the native dialog element, which gives focus trapping, Escape and the backdrop for free. Focus returns to the opener on close.

Open a modal

<button class="btn" data-modal-open="compare">Compare</button>
<dialog class="modal" id="compare" aria-labelledby="compare-title">
  <div class="modal__panel">
    <header class="modal__header"><h2 class="modal__title" id="compare-title">…</h2><button class="modal__close" data-modal-close aria-label="Close">×</button></header>
    <div class="modal__body">…</div>
    <footer class="modal__footer">…</footer>
  </div>
</dialog>

Anatomy

Tabs

Two flavours share one look. Link tabs are anchors, so a server-rendered page can use them for sections without any script. Panel tabs follow the WAI-ARIA tabs pattern.

Link tabs: server rendered, no script

<nav class="tabs" aria-label="Sections of this page">
  <ul class="tabs__list">
    <li><a class="tabs__tab" href="#overview" aria-current="page">Overview</a></li>
    <li><a class="tabs__tab" href="#attributes">Attributes</a></li>
  </ul>
</nav>

Panel tabs: role=tablist with keyboard support

Arrow keys move between tabs; Home and End jump to the ends. The selected tab is remembered in the URL hash when data-tabs="hash".
<div class="tabs" data-tabs>
  <div class="tabs__list" role="tablist">
    <button class="tabs__tab" role="tab" aria-selected="true" aria-controls="p1" id="t1">Stats</button>
  </div>
  <div class="tabs__panel" role="tabpanel" id="p1" aria-labelledby="t1">…</div>
</div>

Vertical

Vertical tabs use a right rule for the active item and move with up and down arrows when scripted.

Tables

The workhorse. Uppercase column headers on the raised surface, numbers right-aligned in tabular figures, entity links in ink colour because the whole column is links. Wide tables scroll inside .table-wrap; the page never scrolls sideways.

Default: dense, striped, hover

Season records
Season Competition Pos P W D L GF GA Pts
2024–25Premier League23820144693474
2023–24Premier League2382855912989
2022–23Premier League2382666884384
2021–22Premier League53822313614869
<div class="table-wrap">
  <table class="table table--dense table--striped table--hover">
    <thead><tr><th scope="col">Season</th><th scope="col" class="table__th--num">Pts</th></tr></thead>
    <tbody><tr><td>2024–25</td><td class="table__cell--num">74</td></tr></tbody>
  </table>
</div>

Blanks are blanks: a partial results line renders dashes, never zeros, and points are never recomputed

Season Competition Pos P W D L GF GA Pts
2023–24Premier League15——————40
2022–23Premier League173881218345736

Sortable headers (client side here; server side in the app) and a sticky head in a bounded scroll region

1Liverpool3825948641+4584
2Arsenal38201446934+3574
3Manchester City3821897244+2871
17Tottenham Hotspur38115226465−138
18Leicester City3867253380−4725
19Ipswich Town38410243682−4622
20Southampton3826302686−6012
<th scope="col" aria-sort="descending"><button class="table__sort">Pts</button></th>
<tr class="table__row--zone-down">…</tr>

Row states, group rows, stacked cells, bars, actions

PlayerPositionCornersScoreActions
Attacking midfielders
AMR18
99.4
Michael Akpovie OliseAMR16
99.8
Unknown person———
Dangling referenceperson_uid 94012860 does not resolve in this version
Mean of listed17

Bordered, small, key/value, footer bar

KitStyleColours
02
00
Reputation187
Level0
StatusActive

Empty table

SeasonClubAppsGoals

No season rows recorded

This version's player_history has no row for this player.

Pagination

Previous and next are always present and disabled rather than hidden at the ends. The summary states the page and total so the reader knows the size of what they are paging through.

Full, on the first page and mid-way

<nav class="pagination" aria-label="Pagination">
  <p class="pagination__summary">Page 3 of 6</p>
  <ul class="pagination__list">
    <li><a class="pagination__link pagination__link--prev" rel="prev" href="?page=2">Previous</a></li>
    <li><a class="pagination__link" href="?page=3" aria-current="page">3</a></li>
    <li><span class="pagination__ellipsis">…</span></li>
    <li><a class="pagination__link pagination__link--next" rel="next" href="?page=4">Next</a></li>
  </ul>
</nav>

Simple, small, centred, last page

Deep pages are bounded

Avatars

No club has an image in the database, so a crest is drawn from the two stored club colours and a letter; a flag from the nation's stored foreground and background. Nothing is invented beyond what the row holds.

Sizes with initials

BSBSBSBSBSBS
<span class="avatar avatar--md"><span class="avatar__initials">BS</span></span>

Silhouette, square, status

PLKTJE

Crests from club colours: solid, split, stripes, hoops

<span class="avatar avatar--xl avatar--crest avatar--stripes" style="--crest-a: #000; --crest-b: #fff">N</span>

Flags from stored nation colours, groups, identity

DRBWBS+55BSBukayo Ayoyinka SakaAMR, Arsenal

Tooltips

CSS only: the text sits in data-tooltip and appears on hover and keyboard focus. The script mirrors it into an aria-describedby node so screen readers get it too.

Positions (hover or focus)

<button class="btn tooltip" data-tooltip="Current ability, on the game's 0 to 200 scale">CA</button>

Wide, term style, on an icon button, and one held open for the guide

100th pctAlways visible

Empty states

An empty state says what is absent and why the database has nothing there, in the interface's voice, and offers the nearest useful move. It never treats a blank as an error.

Default, with an action

No national-team spells recorded

Nothing in person_nation_contract for this person. The 44 international appearances are counted on the player row.

<div class="empty">
  <svg class="empty__icon">…</svg>
  <p class="empty__title">No national-team spells recorded</p>
  <p class="empty__body">Nothing in person_nation_contract for this person.</p>
  <div class="empty__actions"><a class="btn btn--sm" href="#">Browse nations</a></div>
</div>

Search with no hits

Nothing matches “Sakka”

Search matches the start of a name. Check the spelling or try a shorter prefix.

Compact, inside a panel, and bare

Other teams

No other teams recorded

Reserve, U21 and U18 sides would appear here as their own club_team rows.

No partnerships recorded

club_partnership is empty or near-empty in most versions of the source.

Skeleton loaders

Placeholders that hold the shape of the content while a region loads. The container carries aria-busy; the shimmer stops under reduced motion.

Text, heading, avatar, button, input

<div aria-busy="true">
  <span class="skeleton skeleton--heading" aria-hidden="true"></span>
  <div class="skeleton-lines" aria-hidden="true">
    <span class="skeleton skeleton--text"></span>
    <span class="skeleton skeleton--text"></span>
  </div>
</div>

A loading panel: table rows and attribute rows

Squad

Attributes

Attributes

The 1–20 scale as stored, with no conversion. Four colour bands (1–5, 6–10, 11–14, 15–20) plus a blank for “not recorded”, which is never a zero. Bars are optional and off by default, as in the game.

Bands. The value is coloured the way the game colours it; a blank stays blank; an out-of-range byte is flagged, never drawn full width

  • Corners100th pct18
  • Crossing99th pct15
  • Dribbling96th pct13
  • Heading75th pct9
  • Long throws31st pct4
  • Marking—
  • Out of range125
  • Corners18
  • Crossing15
  • Dribbling13
  • Heading9
  • Long throws4
  • Marking—
  • Out of range125
<ul class="attr-list attr-list--striped" role="list">
  <li class="attr attr--elite attr--with-context">
    <span class="attr__name">Corners</span>
    <span class="attr__context">100th pct</span>
    <span class="attr__value">18</span>
    <span class="attr__bar" aria-hidden="true"><i style="--v: 90%"></i></span>
  </li>
  <li class="attr attr--blank"><span class="attr__name">Marking</span><span class="attr__value">—</span></li>
</ul>

The board: technical, mental, physical. Highlighted rows are key attributes for a role

Attributes

Technical

  • Corners18
  • Crossing15
  • Dribbling17
  • Finishing15
  • First touch16

Mental

  • Aggression13
  • Anticipation16
  • Bravery12
  • Composure15
  • Concentration14

Physical

  • Acceleration17
  • Agility16
  • Balance18
  • Jumping reach9
  • Pace15
15–2011–146–101–5Not recorded
<div class="attr-board">
  <div class="attr-board__group"><h3 class="attr-board__title">Technical</h3><ul class="attr-list attr-list--striped">…</ul></div>
  …
</div>

Inline values in a table cell

181394—
<span class="attr-value attr-value--elite">18</span>

Pitch

Position competency drawn where it is played, attack at the top. Five competency colours match the game; a dashed ring is a position with no recorded value, which is not the same as being unable to play there.

Sizes. FM18 and later have no sweeper row; the CM-era databases carry only GK and SW until the decoder is fixed

  • GK—
  • DL8
  • DC—
  • DR—
  • WBL10
  • DM—
  • WBR8
  • ML12
  • MC8
  • MR14
  • AML18
  • AMC—
  • AMR20
  • ST—
Small
  • GK—
  • DL8
  • DC—
  • DR—
  • WBL10
  • DM—
  • WBR8
  • ML12
  • MC8
  • MR14
  • AML18
  • AMC—
  • AMR20
  • ST—
Default, 14 positions
  • GK20
  • SW3
  • DC1
Large, a CM-era goalkeeper
Natural 20Accomplished 15–19Competent 10–14Unconvincing 5–9Awkward 1–4Not recorded
<figure class="pitch">
  <ul class="pitch__positions" role="list">
    <li class="pitch__pos pitch__pos--amr pitch__pos--natural"><abbr title="Attacking midfielder (right)">AMR</abbr><span class="pitch__value">20</span></li>
    <li class="pitch__pos pitch__pos--gk pitch__pos--blank"><abbr title="Goalkeeper">GK</abbr><span class="pitch__value">—</span></li>
  </ul>
</figure>

Position chips for a summary line

AMR 20AML 18MR 14DL 8GK 2DC —
<span class="pos-chip pos-chip--natural">AMR 20</span>

Facts

Label and value rows: the Personal Information panel. Labels are muted and small; values carry the weight. A note after a value gives the unit, the scale or the caveat.

Striped (the game's panel rows), plain, compact, wide label

Full name
Bukayo Ayoyinka Saka
Date of birth
25 years
Nationality
England
Weekly wage
£300,000
Favourite squad number
—
Full name
Bukayo Ayoyinka Saka
Date of birth
25 years
Nationality
England
Weekly wage
£300,000
Favourite squad number
—
Full name
Bukayo Ayoyinka Saka
Date of birth
25 years
Nationality
England
Weekly wage
£300,000
Favourite squad number
—
Full name
Bukayo Ayoyinka Saka
Date of birth
25 years
Nationality
England
Weekly wage
£300,000
Favourite squad number
—
<dl class="facts facts--striped">
  <div class="facts__row">
    <dt class="facts__label">Weekly wage</dt>
    <dd class="facts__value"><span class="money" data-gbp="300000">£300,000</span></dd>
  </div>
</dl>

Two columns and inline

Full name
Bukayo Ayoyinka Saka
Date of birth
25 years
Nationality
England
Weekly wage
£300,000
Favourite squad number
—
Full name
Bukayo Ayoyinka Saka
Date of birth
25 years
Nationality
England
Weekly wage
£300,000
Favourite squad number
—
Founded
1886
Reputation
8650
Capacity
60,704

Stats

One figure and its label in the display face. A tint on the figure means something (a good rating, a deduction) and is never decoration.

Sizes and meaning tints

181Current ability
181Current ability
188Potential ability
44Caps
7.31Average rating
−8Deduction
—Youth rating
<div class="stat">
  <span class="stat__value">181</span>
  <span class="stat__label">Current ability</span>
</div>

Stat row: the game's APPS / MPL / AV RAT strip; centred and start aligned

11Apps
990Minutes
64%Games won
1.82Goals per 90
7.00Av rating
157,940Players in this version
116,944No corners value
40,210Scored

Tiles and inline

1886Founded
60,704seatsCapacityEmirates Stadium
2ndPosition

Ratings

Stars for reputation and role suitability, pills for match ratings, bars for the 0–200 ability scale. The percentile chip states where a value sits in its cohort.

Stars, fractional

<span class="stars" style="--rating: 3.5" role="img" aria-label="3.5 out of 5 stars"></span>

Rating pills, ability bars, percentile, condition

7.856.725.90–100th pct54th pct 96% 71% Injured
<span class="rating-pill rating-pill--good">7.85</span>
<span class="ability"><i style="--v: 90.5%"></i></span>

Radar

The attribute summary polygon. The server renders the SVG with a title and a description; a visually hidden table beside it carries every value for readers who cannot see the shape. Grid recessive, one shape in the accent, a second dashed for comparison.

Sizes

Attribute summary Attribute summary: 6 of 6 values recorded, plotted on a 1 to 20 scale. Attribute summary: 6 of 6 values recorded, plotted on a 1 to 20 scale.
6 of 6 recorded
Attribute summary Attribute summary: 6 of 6 values recorded, plotted on a 1 to 20 scale. Attribute summary: 6 of 6 values recorded, plotted on a 1 to 20 scale.
6 of 6 recordedDerived by averaging the attributes in each group. The database stores no such summary.
<figure class="radar" style="--radar-accent: var(--color-accent)">
  <svg class="radar__chart" viewBox="-140 -140 280 280" role="img" aria-labelledby="…">
    <g class="radar__grid">…</g>
    <polygon class="radar__shape" points="…"/>
    <g class="radar__labels">…</g>
  </svg>
  <figcaption class="radar__caption">…</figcaption>
</figure>

Comparison shape and an accent in a club colour

Attribute summary Attribute summary: 6 of 6 values recorded, plotted on a 1 to 20 scale. Attribute summary: 6 of 6 values recorded, plotted on a 1 to 20 scale. Attribute summary: 6 of 6 values recorded, plotted on a 1 to 20 scale.
This playerCohort mean
Attribute summary Attribute summary: 6 of 6 values recorded, plotted on a 1 to 20 scale. Attribute summary: 6 of 6 values recorded, plotted on a 1 to 20 scale.
Club colour accent

Entity header

The top of every player, club, competition and nation page, and the one place the design is loud: the name set large in the condensed face, the squad-number tile from the game's kit card, and the headline figures at the right.

Player: squad-number tile, prominent name, meta list, tags and headline stats

7

Bukayo Ayoyinka Saka

PlayerENGContracted to 2031
181Current ability
188Potential ability
44Caps
<header class="entity">
  <div class="entity__media"><span class="entity__number" style="--entity-accent: #E20613">7</span></div>
  <div class="entity__body">
    <h1 class="entity__name">Bukayo Ayoyinka Saka</h1>
    <ul class="meta" role="list"><li>AM (R)</li><li><a href="…">Arsenal</a></li></ul>
    <div class="entity__tags">…</div>
  </div>
  <div class="entity__aside"><div class="stat-row">…</div></div>
</header>

Club with a crest, and a person with no squad number or full date of birth

8650Reputation
60,704Capacity
—

Unknown person

Unclassified

Compact, for index pages

Players

  • 157,940 in FM26 Update
  • Everyone with a row in player
  • Page 1 of 6,318

Meta list and versions strip

  • Premier League
  • England
  • 15 Aug 2025
  • Small
  • Muted
  • Divided by hairlines, never punctuation
<ul class="meta" role="list"><li>AM (R)</li><li><a href="…">Arsenal</a></li></ul>
<div class="versions"><span class="versions__label">This player in other versions</span><a class="versions__link" aria-current="page" href="…">FM26<span class="versions__game">Update</span></a>…</div>

Kits

A shirt drawn from the stored colours, with the name above the number as the game prints its kit card. The #kit-shirt symbol lives in the page sprite; its fills are inline var() styles because document CSS does not reach inside a use shadow tree.

Sizes, drawn from two stored colours

7
7
Kane9
England10
Away
<figure class="kit kit--md" style="--kit-body: #E20613; --kit-trim: #FAFAFA; --kit-ink: #FAFAFA">
  <svg class="kit__shirt"><use href="#kit-shirt"></use></svg>
  <span class="kit__name">Saka</span><span class="kit__number">7</span>
</figure>

The kit card: the player-profile hero

Saka7
Squad number 7, club colours
Away7
Kit 1, away
<figure class="kit kit--lg kit--card" style="…">…<figcaption class="kit__caption">Squad number 7</figcaption></figure>

Kit list with captions and the stored colour strip

  • Kit 0, style 2
  • Kit 0, style 1
  • Kit 0, style 0

Charts and timelines

Server-rendered SVG with one job each: a single series per line chart, a legend only when there are two or more, recessive grid, direct labels at the ends, a hover tooltip on every point, and a visually hidden table beside every chart. Follows the data-viz rules: no dual axes, colour follows meaning, text wears text ink.

Line chart

League position by seasonLeague position, 25 seasons.141017202000–012004–052008–092012–132016–172020–212024–252000–01: 22001–02: 12002–03: 22003–04: 12004–05: 22005–06: 42006–07: 42007–08: 32008–09: 42009–10: 32010–11: 42011–12: 32012–13: 42013–14: 42014–15: 32015–16: 22016–17: 52017–18: 62018–19: 52019–20: 82020–21: 82021–22: 52022–23: 22023–24: 22024–25: 222
One series, inverted axis, bands for the top four and bottom three, direct labels at the ends, hover for the season.
League position by season
SeasonLeague position
2000–012
2001–021
2002–032
2003–041
2004–052
2005–064
2006–074
2007–083
2008–094
2009–103
2010–114
2011–123
2012–134
2013–144
2014–153
2015–162
2016–175
2017–186
2018–195
2019–208
2020–218
2021–225
2022–232
2023–242
2024–252
<figure class="chart">
  <svg class="chart__svg" viewBox="0 0 640 200" role="img" aria-labelledby="…">
    <g class="chart__grid">…</g><g class="chart__axis">…</g>
    <path class="chart__line" d="…"/>
    <g class="chart__points"><circle class="chart__hit" data-label="2024–25: 2"/><circle class="chart__point"/></g>
  </svg>
  <figcaption class="chart__caption">…</figcaption>
  <table class="visually-hidden">…</table>
</figure>

Two series and a bar chart

Ability across versions0100200FM19 RFM19 UFM20 RFM20 UFM21 RFM21 UFM22FM23FM24FM26 RFM26 U
Current ability 181Potential ability 188
Two series on one axis, a legend and a label at each end.
Ability across versions
VersionCurrent abilityPotential ability
FM19 R96170
FM19 U112175
FM20 R128178
FM20 U141180
FM21 R155183
FM21 U163185
FM22170186
FM23175187
FM24178188
FM26 R181188
FM26 U181188
Weekly wage across versions£300K£0FM19FM20FM21FM22FM23FM24FM26FM19: £2KFM20: £30KFM21: £30KFM22: £195KFM23: £195KFM24: £195KFM26: £300K
Thin bars from the baseline; hover for the value.
Weekly wage across versions
LabelWage
FM19£2K
FM20£30K
FM21£30K
FM22£195K
FM23£195K
FM24£195K
FM26£300K

Timeline (gantt): absences on a time axis

202420252026
partially torn hamstring (right)
moderate hamstring strain (left)
thigh strain
hip injury
<div class="gantt" style="--gantt-label: 13rem">
  <div class="gantt__axis"><span style="--x: 0%">2024</span>…</div>
  <div class="gantt__row"><span class="gantt__label">…</span><span class="gantt__track"><span class="gantt__bar gantt__bar--major" style="--x: 38%; --w: 10%"></span></span></div>
</div>

Honours cabinet and league pyramid

8Manchester City2021–22, 2022–23, 2023–24 …
7Manchester United2008–09, 2010–11, 2012–13 …
5Chelsea2009–10, 2014–15, 2016–17 …
2Arsenal2001–02, 2003–04
<div class="honours"><div class="honour"><svg class="honour__icon">…</svg><span class="honour__count">8</span><span class="honour__name">Manchester City</span><span class="honour__years">2021–22 …</span></div></div>

Best eleven on the pitch

  • GKRaya160
  • DLLewis-Skelly142
  • DCSaliba165
  • DCGabriel162
  • DRWhite155
  • DMZubimendi158
  • MCRice168
  • MCØdegaard170
  • AMLMartinelli152
  • AMRSaka181
  • STGyökeres163
Best player per slot of a 4-3-3 by current ability.
<figure class="pitch pitch--xi"><ul class="pitch__positions" role="list">
  <li class="pitch__pos pitch__pos--amr"><abbr>AMR</abbr><span class="pitch__name">Saka</span><span class="pitch__value">181</span></li>
</ul></figure>

Data wishlist markers

The mockups include the data the ideal site would show. Where the data does not exist yet, the value is illustrative and marked: a dashed underline inline, a dashed card for a whole panel, a tag in a header, and a per-page list that says where each figure would come from and how far the export is from providing it. The footer toggle hides all of it.

Inline marker: an illustrative value with its source in the title

Weight
72 kg
Trained in England
3,650 days
Best role
<span class="req" data-source="person.weight_kg" title="Wanted: person.weight_kg (in the export)">72 kg</span>

Tags and a requested card

Needs dataIn the exportDerivableNeeds exporting

Finances

Needs exporting
Balance
£210M
Transfer budget
£85M
Financial status
Secure

Illustrative values inside a dashed card.

<section class="card card--req">
  <header class="card__header card__header--start"><h2 class="card__title">Finances</h2><span class="req__tag">Needs exporting</span></header>
  …<span class="sample">£210M</span>…
</section>

The per-page wishlist and the footer toggle that hides every marker

Data wishlist for this page

4 data pointsWhole site
  • person.weight_kgWeight In the exportBeside height on the personal panel.
  • training history per personDays trained in each nation and club Needs exportingDecides home-grown status under every squad rule.
  • attributes weighted by roleBest roles with suitability DerivableLabelled as the site's own derivation.
  • nationality columns beyond nation_uidSecond nationality To confirmConfirm the export can reach it.

What the ideal version of this page shows that the data does not carry yet. Values marked with a dashed underline are illustrative. Each row says where the figure would come from and how far the export is from providing it.

Database controls

Navigation and comparison tools around the database: entity pages themed from their own colours, preset chips, the version timeline, a search scope, a density toggle, a column picker, attribute change arrows and ability stars.

Themed entity header: accent from the entity's stored colours (--entity-accent)

Premier League

Champions 2024–25 Liverpool

  • PL
  • Top division
  • England
Active
187Reputation
20Clubs
<main style="--entity-accent: #310039">
  <header class="entity entity--themed">…</header>
  <nav class="tabs tabs--accent">…</nav>
  <section class="card card--themed">…</section>

Chips for presets and quick links

<div class="chips"><a class="chip" href="…" aria-current="true">Wonderkids</a></div>

Version timeline

  1. CM01/02R
  2. CM02/03R
  3. CM03/04RU
  4. FM05RU
  5. …?
  6. FM19RU
  7. FM20RU
  8. FM21RU
  9. FM22R
  10. FM23R
  11. FM24R
  12. FM26RU
R release, the earliest data for a gameU update, the latestA game has one or both
<ol class="vtl" role="list"><li class="vtl__game vtl__game--current"><span class="vtl__label">FM26</span><span class="vtl__dots"><a class="vtl__dot vtl__dot--release" href="…">R</a><a class="vtl__dot vtl__dot--update is-current" href="…">U</a></span></li></ol>

Search scope, density toggle and column picker

Compact layout uses tighter page and player headers, smaller kits, crests and display type, reduced spacing, and compact table, facts and attribute rows. All content stays available. The preference is remembered in this browser; toggle again to restore the comfortable layout.
Hides cells that carry data-col; remembered per table.
<button class="btn btn--sm btn--icon" data-density-toggle>…</button>
<details class="dropdown" data-colpicker="squad-table">…<label class="checkbox checkbox--sm colpicker__item"><input class="checkbox__input" type="checkbox" data-col="wage" checked>…</label></details>
<td data-col="wage">£300,000</td>

Attribute change arrows and inline stars

  • Corners▲ 1100th pct18
  • Finishing▲ 199th pct15
  • Pace▼ 191st pct15

181Current ability
<li class="attr attr--elite attr--with-context attr--with-delta">
  <span class="attr__name">Corners</span>
  <span class="attr__delta attr__delta--up">▲ 1</span>
  <span class="attr__context">100th pct</span>
  <span class="attr__value">18</span>
</li>