Skip to content

Instantly share code, notes, and snippets.

@fwbrasil
Created June 10, 2025 16:11
Show Gist options
  • Save fwbrasil/dff02794abaffd4a6e00b2e6d4a2288d to your computer and use it in GitHub Desktop.
Save fwbrasil/dff02794abaffd4a6e00b2e6d4a2288d to your computer and use it in GitHub Desktop.
Periodic Table of Elements - HTML/CSS
- var categories = ['data','prelude','core','extension']
// ELEMENT MIXIN TEMPLATE - Updated to include GitHub URL
mixin element(number, symbol, name, description, weight, material, column, row, githubPath)
.element(class=material)(class='c'+column)(class='r'+row)(data-github-path=githubPath)
input.activate(type='radio', name='elements')
input.deactivate(type='radio', name='elements')
.overlay
.square
.model
each item in weight.reverse()
.orbital
- for (var i = 0; i < item; i++)
.electron
.atomic-number= number
.label
.symbol= symbol
.name= name
.description= description
ul.atomic-weight
each item in weight.reverse()
li= item
// PLACEHOLDER MIXIN TEMPLATE
mixin placeholder(number, material, column, row)
.placeholder(class=material)(class='c'+column)(class='r'+row)
.square= number
.wrapper
h1.main-title The Elements of Kyo
each item in categories
input.category-toggle(type='radio', id=item, name='categoxries')
input.category-cancel(type='radio', id='cancel' name='categories')
.periodic-table
// Column 1 (rows 2-7 from top to bottom): Render, Frame, SafeClassTag, Tag, TypeMap, Record
+element(1, 'Rd', 'Render', 'Safe string representation', [1], 'data', 1, 2, 'kyo-data/shared/src/main/scala/kyo/Render.scala')
+element(7, 'Fr', 'Frame', 'Caller introspection', [2,5], 'data', 1, 3, 'kyo-data/shared/src/main/scala/kyo/Frame.scala')
+element(13, 'Sc', 'SafeClassTag', 'Class-based tags', [2,8,3], 'data', 1, 4, 'kyo-data/shared/src/main/scala/kyo/SafeClassTag.scala')
+element(19, 'Tg', 'Tag', 'Generic type tags', [2,8,8,1], 'data', 1, 5, 'kyo-data/shared/src/main/scala/kyo/Tag.scala')
+element(25, 'Tm', 'TypeMap', 'Heterogeneous maps', [2,8,13,2], 'data', 1, 6, 'kyo-data/shared/src/main/scala/kyo/TypeMap.scala')
+element(31, 'Rc', 'Record', 'Polymorphic records', [2,8,18,3], 'data', 1, 7, 'kyo-data/shared/src/main/scala/kyo/Record.scala')
// Column 2 (rows 3-7): Maybe, Result, Chunk, KArray, Text
+element(2, 'Mb', 'Maybe', 'Unboxed optional values', [2], 'data', 2, 3, 'kyo-data/shared/src/main/scala/kyo/Maybe.scala')
+element(8, 'Re', 'Result', 'Unboxed error handling', [2,6], 'data', 2, 4, 'kyo-data/shared/src/main/scala/kyo/Result.scala')
+element(14, 'Ch', 'Chunk', 'Optimized sequences', [2,8,4], 'data', 2, 5, 'kyo-data/shared/src/main/scala/kyo/Chunk.scala')
+element(20, 'Ka', 'KArray', 'Optimized immutable array', [2,8,8,2], 'data', 2, 6, 'kyo-data/shared/src/main/scala/kyo/KArray.scala')
+element(26, 'Tx', 'Text', 'Efficient string manipulation', [2,8,14,2], 'data', 2, 7, 'kyo-data/shared/src/main/scala/kyo/Text.scala')
// Column 3 (rows 2, 4-7): Ansi, Instant, Duration, Schedule
+element(3, 'As', 'Ansi', 'Console pretty printing', [3], 'data', 3, 4, 'kyo-data/shared/src/main/scala/kyo/Ansi.scala')
+element(9, 'Is', 'Instant', 'Time representation', [2,7], 'data', 3, 5, 'kyo-data/shared/src/main/scala/kyo/Instant.scala')
+element(15, 'Dr', 'Duration', 'Time intervals', [2,8,5], 'data', 3, 6, 'kyo-data/shared/src/main/scala/kyo/Duration.scala')
+element(21, 'Sc', 'Schedule', 'Time-based scheduling', [2,8,9,2], 'data', 3, 7, 'kyo-data/shared/src/main/scala/kyo/Schedule.scala')
// Column 4 (rows 3-6): Stream, Sink, Emit, Poll
+element(4, 'St', 'Stream', 'Lazy sequence processing', [4], 'prelude', 4, 4, 'kyo-prelude/shared/src/main/scala/kyo/Stream.scala')
+element(10, 'Sk', 'Sink', 'Stream consumption patterns', [2,8], 'prelude', 4, 5, 'kyo-prelude/shared/src/main/scala/kyo/Sink.scala')
+element(16, 'Em', 'Emit', 'Push-based streaming', [2,8,6], 'prelude', 4, 6, 'kyo-prelude/shared/src/main/scala/kyo/Emit.scala')
+element(22, 'Pl', 'Poll', 'Pull-based streaming', [2,8,10,2], 'prelude', 4, 7, 'kyo-prelude/shared/src/main/scala/kyo/Poll.scala')
// Column 5 (rows 3-6): Env, Layer, Local, Var
+element(5, 'En', 'Env', 'Dependency injection', [5], 'prelude', 5, 4, 'kyo-prelude/shared/src/main/scala/kyo/Env.scala')
+element(11, 'Ly', 'Layer', 'Composable dependencies', [2,8,1], 'prelude', 5, 5, 'kyo-prelude/shared/src/main/scala/kyo/Layer.scala')
+element(17, 'Lc', 'Local', 'Scoped context values', [2,8,7], 'prelude', 5, 6, 'kyo-prelude/shared/src/main/scala/kyo/Local.scala')
+element(23, 'Vr', 'Var', 'State management', [2,8,11,2], 'prelude', 5, 7, 'kyo-prelude/shared/src/main/scala/kyo/Var.scala')
// Column 6 (rows 3-6): Memo, Aspect, Parse, Batch
+element(6, 'Mm', 'Memo', 'Value caching', [6], 'prelude', 6, 4, 'kyo-prelude/shared/src/main/scala/kyo/Memo.scala')
+element(12, 'As', 'Aspect', 'Cross-cutting concerns', [2,8,2], 'prelude', 6, 5, 'kyo-prelude/shared/src/main/scala/kyo/Aspect.scala')
+element(18, 'Pr', 'Parse', 'Text parsing combinators', [2,8,8], 'prelude', 6, 6, 'kyo-prelude/shared/src/main/scala/kyo/Parse.scala')
+element(24, 'Bt', 'Batch', 'Automatic operation batching', [2,8,12,2], 'prelude', 6, 7, 'kyo-prelude/shared/src/main/scala/kyo/Batch.scala')
// Column 7 (rows 2-7): IO, Resource, Abort, Debug, Check, Choice
+element(27, 'IO', 'IO', 'Side effect suspension', [2,8,15,2], 'core', 6, 3, 'kyo-core/shared/src/main/scala/kyo/IO.scala')
+element(32, 'Rs', 'Resource', 'Cleanup guarantees', [2,8,18,4], 'core', 7, 3, 'kyo-core/shared/src/main/scala/kyo/Resource.scala')
+element(37, 'Ab', 'Abort', 'Typed error handling', [2,8,18,9], 'prelude', 7, 4, 'kyo-prelude/shared/src/main/scala/kyo/Abort.scala')
+element(42, 'Db', 'Debug', 'Execution tracing', [2,8,18,14], 'prelude', 7, 5, 'kyo-prelude/shared/src/main/scala/kyo/Debug.scala')
+element(47, 'Ck', 'Check', 'Runtime assertions', [2,8,18,19], 'prelude', 7, 6, 'kyo-prelude/shared/src/main/scala/kyo/Check.scala')
+element(52, 'Ch', 'Choice', 'Non-deterministic branching', [2,8,18,24], 'prelude', 7, 7, 'kyo-prelude/shared/src/main/scala/kyo/Choice.scala')
// Column 8 (rows 2-7): Console, Clock, Log, Random, Adder, Atomic
+element(28, 'Cn', 'Console', 'Terminal I/O', [2,8,16,2], 'core', 8, 2, 'kyo-core/shared/src/main/scala/kyo/Console.scala')
+element(33, 'Cl', 'Clock', 'Time operations', [2,8,18,5], 'core', 8, 3, 'kyo-core/shared/src/main/scala/kyo/Clock.scala')
+element(38, 'Lg', 'Log', 'Convenient logging', [2,8,18,10], 'core', 8, 4, 'kyo-core/shared/src/main/scala/kyo/Log.scala')
+element(43, 'Rn', 'Random', 'Value generation', [2,8,18,15], 'core', 8, 5, 'kyo-core/shared/src/main/scala/kyo/Random.scala')
+element(48, 'Ad', 'Adder', 'Concurrent accumulation', [2,8,18,20], 'core', 8, 6, 'kyo-core/shared/src/main/scala/kyo/Adder.scala')
+element(53, 'At', 'Atomic', 'Thread-safe state', [2,8,18,25], 'core', 8, 7, 'kyo-core/shared/src/main/scala/kyo/Atomic.scala')
// Column 9 (rows 2-7): Async, Retry, Actor, Signal, Fiber, Admission
+element(29, 'As', 'Async', 'Concurrent execution', [2,8,17,2], 'core', 9, 2, 'kyo-core/shared/src/main/scala/kyo/Async.scala')
+element(34, 'Rt', 'Retry', 'Failure recovery', [2,8,18,6], 'core', 9, 3, 'kyo-core/shared/src/main/scala/kyo/Retry.scala')
+element(39, 'Ac', 'Actor', 'Message passing', [2,8,18,11], 'core', 9, 4, 'kyo-core/shared/src/main/scala/kyo/Actor.scala')
+element(44, 'Sg', 'Signal', 'Reactive values', [2,8,18,16], 'core', 9, 5, 'kyo-core/shared/src/main/scala/kyo/Signal.scala')
+element(49, 'Fb', 'Fiber', 'Async primitives', [2,8,18,21], 'core', 9, 6, 'kyo-core/shared/src/main/scala/kyo/Fiber.scala')
+element(54, 'Am', 'Admission', 'Load shedding', [2,8,18,26], 'core', 9, 7, 'kyo-core/shared/src/main/scala/kyo/Admission.scala')
// Column 10 (rows 2-7): Channel, Queue, Meter, Latch, Barrier, Hub
+element(30, 'Ch', 'Channel', 'Fiber communication', [2,8,18,2], 'core', 10, 2, 'kyo-core/shared/src/main/scala/kyo/Channel.scala')
+element(35, 'Qu', 'Queue', 'Concurrent buffer', [2,8,18,7], 'core', 10, 3, 'kyo-core/shared/src/main/scala/kyo/Queue.scala')
+element(40, 'Mt', 'Meter', 'Semaphores and rate limiting', [2,8,18,12], 'core', 10, 4, 'kyo-core/shared/src/main/scala/kyo/Meter.scala')
+element(45, 'Lt', 'Latch', 'Countdown synchronization', [2,8,18,17], 'core', 10, 5, 'kyo-core/shared/src/main/scala/kyo/Latch.scala')
+element(50, 'Br', 'Barrier', 'Rendezvous synchronization', [2,8,18,22], 'core', 10, 6, 'kyo-core/shared/src/main/scala/kyo/Barrier.scala')
+element(55, 'Hb', 'Hub', 'Broadcast messaging', [2,8,18,27], 'core', 10, 7, 'kyo-core/shared/src/main/scala/kyo/Hub.scala')
// Column 11 (rows 1-7): System, Path, Stat, Cache, Memory, Topic, Resolvers
+element(56, 'Sy', 'System', 'Environment access', [2,8,18,28], 'core', 11, 1, 'kyo-core/shared/src/main/scala/kyo/System.scala')
+element(36, 'Ph', 'Path', 'File handling', [2,8,18,8], 'core', 11, 2, 'kyo-core/shared/src/main/scala/kyo/Path.scala')
+element(41, 'St', 'Stat', 'Metrics collection', [2,8,18,13], 'core', 11, 3, 'kyo-core/shared/src/main/scala/kyo/Stat.scala')
+element(46, 'Ca', 'Cache', 'Caching via Caffeine', [2,8,18,18], 'extension', 11, 4, 'kyo-cache/shared/src/main/scala/kyo/Cache.scala')
+element(51, 'Mm', 'Memory', 'Offheap memory access', [2,8,18,23], 'extension', 11, 5, 'kyo-memory/shared/src/main/scala/kyo/Memory.scala')
+element(57, 'Tp', 'Topic', 'IPC/UDP via Aeron', [2,8,18,29], 'extension', 11, 6, 'kyo-topic/shared/src/main/scala/kyo/Topic.scala')
+element(62, 'Rv', 'Resolvers', 'GraphQL via Caliban', [2,8,18,32,2], 'extension', 11, 7, 'kyo-resolvers/shared/src/main/scala/kyo/Resolvers.scala')
// Column 12 (rows 1-7): Direct, Requests, Routes, ZIOs, Cats, Browser, STM
+element(63, 'Di', 'Direct', 'Direct syntax via dotty-cps-async', [2,8,18,32,3], 'extension', 12, 1, 'kyo-direct/shared/src/main/scala/kyo/Direct.scala')
+element(58, 'Rq', 'Requests', 'Http client via Sttp', [2,8,18,30], 'extension', 12, 2, 'kyo-requests/shared/src/main/scala/kyo/Requests.scala')
+element(59, 'Ro', 'Routes', 'Http server via Tapir', [2,8,18,31], 'extension', 12, 3, 'kyo-routes/shared/src/main/scala/kyo/Routes.scala')
+element(60, 'Zi', 'ZIOs', 'Integration with ZIO', [2,8,18,32], 'extension', 12, 4, 'kyo-zios/shared/src/main/scala/kyo/ZIOs.scala')
+element(61, 'Ct', 'Cats', 'Integration with cats-effect', [2,8,18,32,1], 'extension', 12, 5, 'kyo-cats/shared/src/main/scala/kyo/Cats.scala')
+element(64, 'Bw', 'Browser', 'Integration with Playwright', [2,8,18,32,4], 'extension', 12, 6, 'kyo-browser/shared/src/main/scala/kyo/Browser.scala')
+element(65, 'SM', 'STM', 'Optimistic concurrency', [2,8,18,32,5], 'extension', 12, 7, 'kyo-stm/shared/src/main/scala/kyo/STM.scala')
.key
.row
label.data(for='data') kyo-data
label.prelude(for='prelude') kyo-prelude
label.core(for='core') kyo-core
label.extension(for='extension') extensions
// GitHub source viewer iframe
.source-viewer
.source-header
span.source-title View Source
iframe#github-frame(src="about:blank" frameborder="0")

Periodic Table of Elements - HTML/CSS

I created this project to familiarize myself with PUG and Sass and had a ton of fun doing it. CSS only.

A Pen by Flavio W. Brasil on CodePen.

License.

// Add this to CodePen's JS section
document.addEventListener('DOMContentLoaded', function() {
// Dynamically load Prism CSS
const prismCSS = document.createElement('link');
prismCSS.rel = 'stylesheet';
prismCSS.href = 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css';
document.head.appendChild(prismCSS);
// Load Prism JS with dependencies
const loadPrism = new Promise((resolve) => {
const prismCore = document.createElement('script');
prismCore.src = 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js';
prismCore.onload = () => {
// Load Java first (Scala depends on it)
const prismJava = document.createElement('script');
prismJava.src = 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-java.min.js';
prismJava.onload = () => {
// Then load Scala
const prismScala = document.createElement('script');
prismScala.src = 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-scala.min.js';
prismScala.onload = () => resolve();
document.head.appendChild(prismScala);
};
document.head.appendChild(prismJava);
};
document.head.appendChild(prismCore);
});
const elements = document.querySelectorAll('.element');
const baseUrl = 'https://raw.githubusercontent.com/getkyo/kyo/main/';
const githubBaseUrl = 'https://github.com/getkyo/kyo/blob/main/';
// Create the code viewer container
const codeViewer = document.createElement('div');
codeViewer.className = 'code-viewer';
codeViewer.innerHTML = `
<div class="code-header">
<span class="code-title">Loading...</span>
<div class="code-actions">
<a class="code-link" href="#" target="_blank">Open in GitHub</a>
<button class="code-close">×</button>
</div>
</div>
<div class="code-content">
<pre><code class="language-scala"></code></pre>
</div>
`;
document.body.appendChild(codeViewer);
// Get references to elements
const codeTitle = codeViewer.querySelector('.code-title');
const codeLink = codeViewer.querySelector('.code-link');
const codeClose = codeViewer.querySelector('.code-close');
const codeElement = codeViewer.querySelector('code');
const preElement = codeViewer.querySelector('pre');
// Style the code viewer
const style = document.createElement('style');
style.textContent = `
.code-viewer {
position: fixed;
bottom: -60vh;
left: 0;
right: 0;
height: 60vh;
background: #1a1d24;
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.5);
transition: bottom 0.3s ease-in-out;
z-index: 1000;
display: flex;
flex-direction: column;
border-top: 2px solid rgba(255, 255, 255, 0.1);
}
.code-viewer * {
text-shadow: none !important;
}
.code-viewer.active {
bottom: 0;
}
.code-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 20px;
background: #101318;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
flex-shrink: 0;
}
.code-title {
color: #fff;
font-size: 14px;
font-weight: 500;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
.code-actions {
display: flex;
gap: 15px;
align-items: center;
}
.code-link {
color: #4ecdc4;
text-decoration: none;
font-size: 13px;
transition: opacity 0.2s;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
.code-link:hover {
opacity: 0.8;
}
.code-close {
background: none;
border: none;
color: #fff;
font-size: 24px;
cursor: pointer;
padding: 0;
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
transition: background-color 0.2s;
}
.code-close:hover {
background-color: rgba(255, 255, 255, 0.1);
}
.code-content {
flex: 1;
overflow: auto;
background: #282c34;
}
.code-content pre {
margin: 0;
padding: 20px;
min-height: 100%;
box-sizing: border-box;
background: transparent !important;
color: #abb2bf !important;
}
.code-content code {
font-family: 'Fira Code', 'Consolas', 'Monaco', monospace;
font-size: 13px;
line-height: 1.6;
background: transparent !important;
color: #abb2bf !important;
text-shadow: none !important;
}
/* Force Prism styles */
.code-content pre[class*="language-"],
.code-content code[class*="language-"] {
color: #abb2bf !important;
background: transparent !important;
text-shadow: none !important;
}
/* Custom scrollbar for code viewer */
.code-content::-webkit-scrollbar {
width: 10px;
height: 10px;
}
.code-content::-webkit-scrollbar-track {
background: #1a1d24;
}
.code-content::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.2);
border-radius: 5px;
}
.code-content::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.3);
}
/* Loading state */
.code-viewer.loading .code-content::after {
content: 'Loading...';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: rgba(255, 255, 255, 0.5);
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
text-shadow: none !important;
}
`;
document.head.appendChild(style);
// Handle element clicks
elements.forEach(element => {
// Listen for the radio button change instead of click
const activateRadio = element.querySelector('input.activate');
const deactivateRadio = element.querySelector('input.deactivate');
activateRadio.addEventListener('change', async function() {
if (this.checked) {
const githubPath = element.getAttribute('data-github-path');
const elementName = element.querySelector('.name').textContent;
const elementSymbol = element.querySelector('.symbol').textContent;
if (githubPath) {
// Update header
codeTitle.textContent = `${elementSymbol} - ${elementName}`;
codeLink.href = githubBaseUrl + githubPath;
// Show viewer and add loading state
codeViewer.classList.add('active', 'loading');
codeElement.textContent = 'Loading...';
try {
// Fetch the raw code
const response = await fetch(baseUrl + githubPath);
const code = await response.text();
// Update code content
codeElement.textContent = code;
// Wait for Prism to load, then apply syntax highlighting
loadPrism.then(() => {
Prism.highlightElement(codeElement);
});
// Remove loading state
codeViewer.classList.remove('loading');
// Scroll to top
preElement.scrollTop = 0;
} catch (error) {
console.error('Failed to fetch code:', error);
codeElement.textContent = `// Error loading file: ${error.message}\n// Please try opening directly in GitHub`;
codeViewer.classList.remove('loading');
}
}
}
});
// Listen for deactivation to close the code viewer
deactivateRadio.addEventListener('change', function() {
if (this.checked) {
codeViewer.classList.remove('active');
}
});
});
// Close button handler
codeClose.addEventListener('click', function() {
codeViewer.classList.remove('active');
});
// Click outside to close (optional)
document.addEventListener('click', function(e) {
if (!e.target.closest('.element') && !e.target.closest('.code-viewer')) {
codeViewer.classList.remove('active');
}
});
// Keyboard shortcut to close (ESC key)
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
codeViewer.classList.remove('active');
}
});
});
$bgColor: #101318
$gridGap: 5px
// Updated colors for Scala library categories
$dataColor: #ecbe59
$preludeColor: #4ecdc4 // Changed from red to a positive teal/cyan
$coreColor: #52ee61
$extensionColor: #759fff
body
background: $bgColor
text-shadow: 0 0 0.4vw currentColor
margin: 0
padding: 0
min-height: 100vh
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif
display: flex
align-items: center
justify-content: center
.wrapper
position: relative
overflow: hidden
padding: 40px
width: 90vw
max-width: 1200px
display: flex
flex-direction: column
align-items: center
> input
-webkit-appearance: none
position: fixed
left: 0
top: 0
width: 100%
height: 100%
visibility: hidden
opacity: 0
pointer-events: none
// Title styling
.main-title
text-align: center
color: #fff
font-size: 2.5rem
margin: 0 0 30px 0
font-weight: 300
letter-spacing: 0.1em
text-transform: uppercase
opacity: 0.9
width: 100%
.periodic-table
display: grid
grid-gap: $gridGap
grid-template-columns: repeat(12, 1fr)
width: 100%
max-width: 900px
margin: 0 auto
// --------------------------------------
// ELEMENT
.element
position: relative
font-size: 0.7rem
padding-bottom: 100%
cursor: pointer
color: #fff
transition: 500ms
.overlay
position: fixed
z-index: 1
left: 0
right: 0
top: 0
bottom: 0
background-color: $bgColor
opacity: 0
pointer-events: none
transition: 500ms
.square
position: absolute
left: 0
top: 0
width: 100%
height: 100%
border: 2px solid
box-sizing: border-box
background: $bgColor
display: flex
flex-direction: column
justify-content: center
align-items: center
transition-property: transform, z-index, left, right, top, bottom
transition-duration: 100ms, 0ms, 200ms, 200ms, 200ms, 200ms
transition-delay: 0ms, 100ms, 0ms, 0ms, 0ms, 0ms
.atomic-number
position: absolute
left: 0
top: 0
padding: 2px
.label
text-align: center
transition: 200ms
.symbol
font-size: 1.5rem
.name
font-size: 0.6rem
// Description (atomic-mass) - hidden in main view, shown only when expanded
.description
position: absolute
left: 0
right: 0
bottom: 0
padding: 2px
text-align: center
font-size: 0.55rem
line-height: 1.2
opacity: 0
display: none
transition: 500ms
overflow: hidden
word-wrap: break-word
.atomic-weight
display: none !important // Add !important
visibility: hidden // Add this line
position: absolute
right: 0
top: 0
list-style: none
margin: 0
padding: 2px
opacity: 0
transition: 500ms
text-align: right
.model
display: none
position: absolute
left: -500%
right: -500%
top: -500%
bottom: -500%
transform: scale(0.1)
.orbital
position: absolute
left: 0
right: 0
top: 0
bottom: 0
border: 5px solid
border-radius: 50%
opacity: 0.25
@for $i from 1 through 7
&:nth-child(#{$i})
margin: 10% + 5.5 * ($i - 1)
animation-duration: 40s - 6 * ($i - 1)
.electron
position: absolute
left: 0
right: 0
top: 0
bottom: 0
&::before
content: ""
position: absolute
left: calc(50% - 0.7vw)
top: -0.7vw
width: 1.4vw
height: 1.4vw
background-color: currentColor
border-radius: 50%
opacity: 0.75
@for $i from 1 through 32
@for $a from 1 through $i
&:nth-last-child(#{$i}):first-child ~ .electron:nth-child(#{$a})
transform: rotate((360deg/$i)*($a - 1))
input[type="radio"]
-webkit-appearance: none
position: absolute
z-index: 2
left: 0
top: 0
width: 100%
height: 100%
opacity: 0
cursor: pointer
outline: none
&.activate
&:hover ~ .square
z-index: 2
transform: scale(1.35)
transition-delay: 0ms
outline: none
pointer-events: none
&:checked + input[type="radio"].deactivate
z-index: 3
pointer-events: all
&:checked ~ .overlay
opacity: 0.75
&:checked ~ .square
z-index: 3
transform: scale(3)
transition-duration: 500ms, 0ms, 200ms, 200ms, 200ms, 200ms
transition-delay: 0ms
outline: none
cursor: auto
.label
transition-duration: 500ms
transform: scale(0.75)
.atomic-weight
opacity: 1
transition: 500ms
display: block
// Show description when expanded
.description
opacity: 1
display: block
transition: 500ms
.model
display: block
animation: fade-in
animation-duration: 1s
.orbital
animation-name: rotate
animation-timing-function: linear
animation-iteration-count: infinite
&.deactivate
position: fixed
display: block
z-index: 1
opacity: 0
pointer-events: none
&:checked ~ .square
z-index: 1
// --------------------------------------
// PLACEHOLDER
.placeholder
position: relative
z-index: -1
font-size: 1vw
padding-bottom: 100%
color: #fff
transition: 500ms
.square
position: absolute
left: 0
top: 0
width: 100%
height: 100%
border: 2px solid
box-sizing: border-box
display: flex
flex-direction: column
justify-content: center
align-items: center
opacity: 0.5
// --------------------------------------
// GAP
.gap
position: relative
padding-bottom: 100%
transition: 500ms
&::before
content: ""
position: absolute
left: 50%
top: 0
width: 50%
height: calc(200% + #{$gridGap} * 2 - 4px)
border-width: 0 0 2px 2px
border-style: solid
margin-left: -1px
color: #fff
opacity: 0.2
// --------------------------------------
// COLORS - Updated for Scala library categories
.data
color: $dataColor
.prelude
color: $preludeColor
.core
color: $coreColor
.extension
color: $extensionColor
// --------------------------------------
// ROWS & COLUMNS
@for $i from 1 through 10
.r#{$i}
grid-row: $i
@for $i from 1 through 12
.c#{$i}
grid-column: $i
// --------------------------------------
// SHIFT EDGE ELEMENTS ON ZOOM
.r1 input[type="radio"].activate:checked ~ .square
top: 100%
.r10 input[type="radio"].activate:checked ~ .square
top: -100%
.c1 input[type="radio"].activate:checked ~ .square
left: 100%
.c12 input[type="radio"].activate:checked ~ .square
left: -100%
// --------------------------------------
// ANIMATIONS
@keyframes rotate
from
transform: rotate(0deg)
to
transform: rotate(360deg)
@keyframes fade-in
from
opacity: 0
to
opacity: 1
@keyframes noise
0%, 100%
background-position: 0 0
10%
background-position: -5% -10%
20%
background-position: -15% 5%
30%
background-position: 7% -25%
40%
background-position: 20% 25%
50%
background-position: -25% 10%
60%
background-position: 15% 5%
70%
background-position: 0% 15%
80%
background-position: 25% 35%
90%
background-position: -10% 10%
// --------------------------------------
// KEY
.key
position: relative
z-index: 1
grid-row: 1
grid-column-start: 1
grid-column-end: 5
font-size: 0.9rem
line-height: 1.5
display: flex
align-items: center
pointer-events: none
user-select: none
.row
position: relative
display: flex
width: 100%
justify-content: space-between
label
opacity: 0.85
cursor: pointer
transition: 120ms
pointer-events: all
&:hover
opacity: 1 !important
// --------------------------------------
// CATEGORY TOGGLES - Updated for Scala library categories
#data:checked ~ .periodic-table .element:not(.data),
#prelude:checked ~ .periodic-table .element:not(.prelude),
#core:checked ~ .periodic-table .element:not(.core),
#extension:checked ~ .periodic-table .element:not(.extension),
#data:checked ~ .periodic-table .placeholder,
#prelude:checked ~ .periodic-table .placeholder,
#core:checked ~ .periodic-table .placeholder,
#extension:checked ~ .periodic-table .placeholder
opacity: 0.15
pointer-events: none
#data:checked ~ .periodic-table .key label:not(.data),
#prelude:checked ~ .periodic-table .key label:not(.prelude),
#core:checked ~ .periodic-table .key label:not(.core),
#extension:checked ~ .periodic-table .key label:not(.extension)
opacity: 0.65
.category-toggle:checked ~ .category-cancel
visibility: visible
pointer-events: all
cursor: pointer
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment