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 down to up across a group, and metallic character (surrendering electrons to other atoms) increasing in the opposite direction.
#import "@preview/cetz:0.5.2": canvas, draw
#import draw: content, rect
#set page(width: auto, height: auto, margin: 15pt, fill: none)
#set text(size: 12pt)
// Element colors
#let colors = (
alkali-metal: rgb("#8989ff"),
alkaline-earth: rgb("#89a9ff"),
metal: rgb("#89c9ff"),
metalloid: rgb("#ffa959"),
nonmetal: rgb("#59d9d9"),
halogen: rgb("#ffff59"),
noble-gas: rgb("#89ff89"),
lanthanide: rgb("#ff8989"),
synthetic: rgb("#525252"),
)
// Element data
#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),
),
)
// Lanthanide data
#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"),
)
// Actinide data
#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"),
)
#let element(number, mass, symbol, name, fill: rgb("#cdd3da"), text-color: 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: text-color)[#symbol]\
#v(1fr)
#text(size: 13pt)[#name]
]
}
#canvas({
let cell-size = 3.25 // Increased cell size
let (start-x, start-y) = (0, 0)
let lanthanide-gap = 2.5 // Gap before lanthanides/actinides
// Function to calculate element position
let pos(group, period) = {
let y-offset = if period > 7 { lanthanide-gap } else { 0 }
let x = start-x + (group - 1) * cell-size
let y = start-y - (period - 1) * cell-size - y-offset
(x, y)
}
// The f-block rows hang below the main table, starting under group 3
let special-pos(num, is-actinide: false) = {
let (row, first) = if is-actinide { (9, 89) } else { (8, 57) }
pos(num - first + 3, row)
}
for period in range(1, elements.len() + 1) {
for group in range(1, 19) {
let data = elements.at(period - 1).at(group - 1)
if data != none {
content(pos(group, period), element(
..data.slice(0, 4),
fill: data.at(4),
))
}
}
}
// Lanthanides
for (idx, data) in lanthanides.enumerate() {
content(special-pos(57 + idx), element(..data, fill: colors.lanthanide))
}
// Actinides
for (idx, data) in actinides.enumerate() {
// Ac through U occur naturally; everything past uranium is man-made, shown in gray
let text-color = if idx <= 3 { black } else { colors.synthetic }
content(
special-pos(89 + idx, is-actinide: true),
element(..data, fill: colors.lanthanide, text-color: text-color),
)
}
// Period labels
for period in range(1, 8) {
content(
(start-x - cell-size * 0.6, start-y - (period - 1) * cell-size),
text(size: 16pt, weight: "bold")[#period],
)
}
// Group labels
let groups = "IA IIA IIIB IVB VB VIB VIIB VIIIB VIIIB VIIIB IB IIB IIIA IVA VA VIA VIIA VIIIA".split(
" ",
)
// Find first element in each column
for (num, label) in groups.enumerate(start: 1) {
let first-period = if num == 1 { 1 } else if num == 2 { 2 } else if (
num <= 12
) { 4 } else { 2 }
let (x, y) = pos(num, first-period)
content((x, y + cell-size * 0.7), box(width: 3cm)[
#text(size: 14pt, weight: "bold")[#num #h(1fr) #label]
])
}
// Legend
let legend-start = (start-x - 0.5 * cell-size, start-y - 6.8 * cell-size)
let legend-items = (
("AlkaliMetal", colors.alkali-metal),
("AlkalineEarth etal", colors.alkaline-earth),
("TransitionMetal", colors.metal),
("Metalloid", colors.metalloid),
("Nonmetal", colors.nonmetal),
("Halogen", colors.halogen),
("NobleGas", colors.noble-gas),
("LanthanideActinide", colors.lanthanide),
)
for (idx, (label, color)) in legend-items.enumerate() {
let y-offset = idx
rect(
(legend-start.at(0), legend-start.at(1) - y-offset),
(legend-start.at(0) + 0.8, legend-start.at(1) - y-offset - 0.8),
fill: color,
stroke: 0.7pt,
)
content(
(legend-start.at(0) + 1, legend-start.at(1) - y-offset - 0.4),
text(size: 14pt)[#label],
anchor: "west",
)
}
// Element key
let legend = element("Z", "mass", text("Symbol", size: 22pt), "Name")
content((12, -4), legend)
content((16.5, -4), text(size: 18pt)[
black: natural\
#text(fill: colors.synthetic)[gray: man-made]
])
})