home

Periodic Table

Creator: Ivan Griffin (original)

The periodic table of elements, a graphic formulation of the periodic dependence of elemental properties on their atomic numbers. The table is divided into four roughly rectangular areas called blocks. Rows are called periods, columns are groups. Elements from the same group show similar chemical characteristics. Trends run through the periodic table, with nonmetallic character (keeping their own electrons) increasing from left to right across a period and from bottom to top within a group, and metallic character (surrendering electrons to other atoms) increasing in the opposite direction. Symbols of man-made transuranic elements (Z > 92) are shown in gray.


Periodic Table

Download

PNG PDF SVG

Code

periodic-table.typ (245 lines)
#import "@preview/cetz:0.5.3": canvas, draw
#import draw: content, rect

#set page(width: auto, height: auto, margin: 15pt, fill: none)
#set text(size: 12pt)

// Alkali and lanthanide fills stay light enough that their mid-tone dark-mode inversion
// keeps black text and the gray man-made symbols readable.
#let colors = (
  alkali-metal: rgb("#9b9bff"),
  alkaline-earth: rgb("#89a9ff"),
  metal: rgb("#89c9ff"),
  metalloid: rgb("#ffa959"),
  nonmetal: rgb("#59d9d9"),
  halogen: rgb("#ffff59"),
  noble-gas: rgb("#89ff89"),
  lanthanide: rgb("#ffa0a0"),
  synthetic: rgb("#444444"),
)

#let elements = (
  // Period 1
  (
    (1, 1.0079, "H", "Hydrogen", colors.nonmetal),
    ..(none,) * 16,
    (2, 4.0025, "He", "Helium", colors.noble-gas),
  ),
  // Period 2
  (
    (3, 6.941, "Li", "Lithium", colors.alkali-metal),
    (4, 9.0122, "Be", "Beryllium", colors.alkaline-earth),
    ..(none,) * 10,
    (5, 10.811, "B", "Boron", colors.metalloid),
    (6, 12.011, "C", "Carbon", colors.nonmetal),
    (7, 14.007, "N", "Nitrogen", colors.nonmetal),
    (8, 15.999, "O", "Oxygen", colors.nonmetal),
    (9, 18.998, "F", "Fluorine", colors.halogen),
    (10, 20.180, "Ne", "Neon", colors.noble-gas),
  ),
  // Period 3
  (
    (11, 22.990, "Na", "Sodium", colors.alkali-metal),
    (12, 24.305, "Mg", "Magnesium", colors.alkaline-earth),
    ..(none,) * 10,
    (13, 26.982, "Al", "Aluminum", colors.metal),
    (14, 28.086, "Si", "Silicon", colors.metalloid),
    (15, 30.974, "P", "Phosphorus", colors.nonmetal),
    (16, 32.065, "S", "Sulfur", colors.nonmetal),
    (17, 35.453, "Cl", "Chlorine", colors.halogen),
    (18, 39.948, "Ar", "Argon", colors.noble-gas),
  ),
  // Period 4
  (
    (19, 39.098, "K", "Potassium", colors.alkali-metal),
    (20, 40.078, "Ca", "Calcium", colors.alkaline-earth),
    (21, 44.956, "Sc", "Scandium", colors.metal),
    (22, 47.867, "Ti", "Titanium", colors.metal),
    (23, 50.942, "V", "Vanadium", colors.metal),
    (24, 51.996, "Cr", "Chromium", colors.metal),
    (25, 54.938, "Mn", "Manganese", colors.metal),
    (26, 55.845, "Fe", "Iron", colors.metal),
    (27, 58.933, "Co", "Cobalt", colors.metal),
    (28, 58.693, "Ni", "Nickel", colors.metal),
    (29, 63.546, "Cu", "Copper", colors.metal),
    (30, 65.39, "Zn", "Zinc", colors.metal),
    (31, 69.723, "Ga", "Gallium", colors.metal),
    (32, 72.64, "Ge", "Germanium", colors.metalloid),
    (33, 74.922, "As", "Arsenic", colors.metalloid),
    (34, 78.96, "Se", "Selenium", colors.nonmetal),
    (35, 79.904, "Br", "Bromine", colors.halogen),
    (36, 83.8, "Kr", "Krypton", colors.noble-gas),
  ),
  // Period 5
  (
    (37, 85.468, "Rb", "Rubidium", colors.alkali-metal),
    (38, 87.62, "Sr", "Strontium", colors.alkaline-earth),
    (39, 88.906, "Y", "Yttrium", colors.metal),
    (40, 91.224, "Zr", "Zirconium", colors.metal),
    (41, 92.906, "Nb", "Niobium", colors.metal),
    (42, 95.94, "Mo", "Molybdenum", colors.metal),
    (43, 96, "Tc", "Technetium", colors.metal),
    (44, 101.07, "Ru", "Ruthenium", colors.metal),
    (45, 102.91, "Rh", "Rhodium", colors.metal),
    (46, 106.42, "Pd", "Palladium", colors.metal),
    (47, 107.87, "Ag", "Silver", colors.metal),
    (48, 112.41, "Cd", "Cadmium", colors.metal),
    (49, 114.82, "In", "Indium", colors.metal),
    (50, 118.71, "Sn", "Tin", colors.metal),
    (51, 121.76, "Sb", "Antimony", colors.metalloid),
    (52, 127.6, "Te", "Tellurium", colors.metalloid),
    (53, 126.9, "I", "Iodine", colors.halogen),
    (54, 131.29, "Xe", "Xenon", colors.noble-gas),
  ),
  // Period 6
  (
    (55, 132.91, "Cs", "Cesium", colors.alkali-metal),
    (56, 137.33, "Ba", "Barium", colors.alkaline-earth),
    ("57-71", "", text("La-Lu", size: 28pt), "Lanthanide", colors.lanthanide),
    (72, 178.49, "Hf", "Hafnium", colors.metal),
    (73, 180.95, "Ta", "Tantalum", colors.metal),
    (74, 183.84, "W", "Tungsten", colors.metal),
    (75, 186.21, "Re", "Rhenium", colors.metal),
    (76, 190.23, "Os", "Osmium", colors.metal),
    (77, 192.22, "Ir", "Iridium", colors.metal),
    (78, 195.08, "Pt", "Platinum", colors.metal),
    (79, 196.97, "Au", "Gold", colors.metal),
    (80, 200.59, "Hg", "Mercury", colors.metal),
    (81, 204.38, "Tl", "Thallium", colors.metal),
    (82, 207.2, "Pb", "Lead", colors.metal),
    (83, 208.98, "Bi", "Bismuth", colors.metal),
    (84, 209, "Po", "Polonium", colors.metalloid),
    (85, 210, "At", "Astatine", colors.halogen),
    (86, 222, "Rn", "Radon", colors.noble-gas),
  ),
  // Period 7
  (
    (87, 223, "Fr", "Francium", colors.alkali-metal),
    (88, 226, "Ra", "Radium", colors.alkaline-earth),
    ("89-103", "", text("Ac-Lr", size: 28pt), "Actinide", colors.lanthanide),
    (104, 261, "Rf", "Rutherfordium", colors.metal),
    (105, 262, "Db", "Dubnium", colors.metal),
    (106, 266, "Sg", "Seaborgium", colors.metal),
    (107, 264, "Bh", "Bohrium", colors.metal),
    (108, 277, "Hs", "Hassium", colors.metal),
    (109, 268, "Mt", "Meitnerium", colors.metal),
    (110, 281, "Ds", "Darmstadtium", colors.metal),
    (111, 280, "Rg", "Roentgenium", colors.metal),
    (112, 285, "Cn", "Copernicium", colors.metal),
    (113, 284, "Nh", "Nihonium", colors.metal),
    (114, 289, "Fl", "Flerovium", colors.metal),
    (115, 288, "Mc", "Moscovium", colors.metal),
    (116, 293, "Lv", "Livermorium", colors.metal),
    (117, 294, "Ts", "Tennessine", colors.halogen),
    (118, 294, "Og", "Oganesson", colors.noble-gas),
  ),
)

#let lanthanides = (
  (57, 138.91, "La", "Lanthanum"),
  (58, 140.12, "Ce", "Cerium"),
  (59, 140.91, "Pr", "Praseodymium"),
  (60, 144.24, "Nd", "Neodymium"),
  (61, 145, "Pm", "Promethium"),
  (62, 150.36, "Sm", "Samarium"),
  (63, 151.96, "Eu", "Europium"),
  (64, 157.25, "Gd", "Gadolinium"),
  (65, 158.93, "Tb", "Terbium"),
  (66, 162.50, "Dy", "Dysprosium"),
  (67, 164.93, "Ho", "Holmium"),
  (68, 167.26, "Er", "Erbium"),
  (69, 168.93, "Tm", "Thulium"),
  (70, 173.04, "Yb", "Ytterbium"),
  (71, 174.97, "Lu", "Lutetium"),
)

#let actinides = (
  (89, 227, "Ac", "Actinium"),
  (90, 232.04, "Th", "Thorium"),
  (91, 231.04, "Pa", "Protactinium"),
  (92, 238.03, "U", "Uranium"),
  (93, 237, "Np", "Neptunium"),
  (94, 244, "Pu", "Plutonium"),
  (95, 243, "Am", "Americium"),
  (96, 247, "Cm", "Curium"),
  (97, 247, "Bk", "Berkelium"),
  (98, 251, "Cf", "Californium"),
  (99, 252, "Es", "Einsteinium"),
  (100, 257, "Fm", "Fermium"),
  (101, 258, "Md", "Mendelevium"),
  (102, 259, "No", "Nobelium"),
  (103, 262, "Lr", "Lawrencium"),
)

// Elements past uranium (Z > 92) are man-made and get a gray symbol.
#let element(number, mass, symbol, name, fill: rgb("#cdd3da")) = {
  let symbol-color = if type(number) == int and number > 92 { colors.synthetic } else { black }
  box(width: 3cm, height: 3cm, fill: fill, stroke: 0.7pt, inset: 4pt)[
    #set align(center)
    #text(size: 18pt, weight: "bold")[#number #h(1fr) #mass]\
    #v(1fr)
    #text(size: 40pt, weight: "bold", fill: symbol-color)[#symbol]\
    #v(1fr)
    #text(size: 13pt)[#name]
  ]
}

#canvas({
  let cell-size = 3.25
  let lanthanide-gap = 2.5 // extra gap above the f-block rows (periods 8 and 9)
  let pos(group, period) = (
    (group - 1) * cell-size,
    -(period - 1) * cell-size - if period > 7 { lanthanide-gap } else { 0 },
  )

  for (period, row) in elements.enumerate(start: 1) {
    for (group, data) in row.enumerate(start: 1) {
      if data != none { content(pos(group, period), element(..data.slice(0, 4), fill: data.at(4))) }
    }
  }

  // The f-block rows hang below the main table, starting under group 3
  for (period, series) in ((8, lanthanides), (9, actinides)) {
    for (idx, data) in series.enumerate() {
      content(pos(idx + 3, period), element(..data, fill: colors.lanthanide))
    }
  }

  for period in range(1, 8) {
    content((rel: (-cell-size * 0.6, 0), to: pos(1, period)), text(
      size: 16pt,
      weight: "bold",
    )[#period])
  }

  // Group labels sit above the first element in each column
  let groups = "IA IIA IIIB IVB VB VIB VIIB VIIIB VIIIB VIIIB IB IIB IIIA IVA VA VIA VIIA VIIIA".split()
  for (num, label) in groups.enumerate(start: 1) {
    let first-period = if num in (1, 18) { 1 } else if num <= 2 or num >= 13 { 2 } else { 4 }
    content((rel: (0, cell-size * 0.7), to: pos(num, first-period)), box(width: 3cm)[
      #text(size: 14pt, weight: "bold")[#num #h(1fr) #label]
    ])
  }

  let (legend-x, legend-y) = (-0.5 * cell-size, -6.8 * cell-size)
  for (idx, (label, color)) in (
    ("Alkali Metal", colors.alkali-metal),
    ("Alkaline Earth Metal", colors.alkaline-earth),
    ("Transition/Other Metal", colors.metal),
    ("Metalloid", colors.metalloid),
    ("Nonmetal", colors.nonmetal),
    ("Halogen", colors.halogen),
    ("Noble Gas", colors.noble-gas),
    ("Lanthanide & Actinide", colors.lanthanide),
  ).enumerate() {
    rect((legend-x, legend-y - idx), (rel: (0.8, -0.8)), fill: color, stroke: 0.7pt, name: "swatch")
    content((rel: (0.2, 0), to: "swatch.east"), text(size: 14pt, label), anchor: "west")
  }

  // Element key
  content((12, -4), element("Z", "mass", text("Symbol", size: 22pt), "Name"), name: "key")
  content((rel: (4.5, 0), to: "key"), text(size: 18pt)[
    black: natural\
    #text(fill: colors.synthetic)[gray: man-made]
  ])
})