Upgrade to Pro — share decks privately, control downloads, hide ads and more …

All you need is CSS

Radoslav Stankov
June 13, 2025
180

All you need is CSS

Radoslav Stankov

June 13, 2025

Transcript

96 slides
  1. !

  2. "

  3. % LIVO Architecture & Ruby on Rails ' No JavaScript

    ( No custom CSS, use Tailwind ) Extensive e2e tests * Focus on domain
  4. +

  5. % LIVO Architecture & Ruby on Rails ' No JavaScript

    ( No custom CSS, use Tailwind ) Extensive e2e tests * Focus on domain
  6. , How to avoid writing code checklist - reduce scope,

    by adjusting business requirement . use build-in feature of the browser / use feature from core platform - Next / React / Angular ... 0 use type system 1 move to logic backend 2 (only when I really have to) use 3rd party library (browser edition)
  7. , How to avoid writing code checklist - reduce scope,

    by adjusting business requirement . use build-in feature of the browser / use feature from core platform - Next / React / Angular ... 0 use type system 1 move to logic backend 2 (only when I really have to) use 3rd party library (browser edition)
  8. function MyButton() { const [isHovered, setIsHovered] = useState(false); const className

    = isHovered ? 'button button-hover' : 'button'; const onMouseEnter = () => setIsHovered(true); const onMouseLeave = () => setIsHovered(false); return ( <button className={className} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>Button</button> ); }
  9. <details> <summary>System Requirements</summary> <p> Requires a computer running an operating

    system. The computer must have some memory and ideally some kind of long-term storage. An input device as well as some form of output device is recommended. </p> </details>
  10. @media (max-width: 640px) { .table-component, .table-component thead, .table-component tbody, .table-component

    tfoot, .table-component tr { display: block; } .table-component tbody td { display: flex; } .table-component tbody td:not(.actions):before { content: attr(title); flex: 0 1 35%; display: block; white-space: nowrap; } }
  11. @media (max-width: 640px) { .table-component, .table-component thead, .table-component tbody, .table-component

    tfoot, .table-component tr { display: block; } .table-component tbody td { display: flex; } .table-component tbody td:not(.actions):before { content: attr(title); flex: 0 1 35%; display: block; white-space: nowrap; } }
  12. @media (max-width: 640px) { .table-component, .table-component thead, .table-component tbody, .table-component

    tfoot, .table-component tr { display: block; } .table-component tbody td { display: flex; } .table-component tbody td:not(.actions):before { content: attr(title); flex: 0 1 35%; display: block; white-space: nowrap; } }
  13. @media (max-width: 640px) { .table-component, .table-component thead, .table-component tbody, .table-component

    tfoot, .table-component tr { display: block; } .table-component tbody td { display: flex; } .table-component tbody td:not(.actions):before { content: attr(title); flex: 0 1 35%; display: block; white-space: nowrap; } }
  14. 3 Accessible 4 Mobile friendly 5 All batteries include ➡

    No extra code 7 Single date, no range 7 Style doesn't match our site <input type="date">
  15. 3 Accessible 4 Build-in backdrop 5 Auto handling of forms

    (example: auto-focus) 8 Stops scrolling of back page 9 Auto handle of ESC : Style as you wish 7 JavaScript to trigger the modal version 7 JavaScript need to close dialog when click backdrop <dialog>
  16. import { setEventListners } from './utils'; setEventListners(document, { '[data-dialog]:click': (e)

    => { document .getElementById(e.target.closest('[data-dialog]').dataset.dialog) ?.showModal(); }, 'dialog:click': (e) => { if (e.target.tagName === 'DIALOG') { e.target.close(); } }, });
  17. /* Tooltip base styles for any element with a title

    attribute */ [title] { position: relative; cursor: pointer; display: inline-block; } /* Hidden before hover */ [title]::before, [title]::after { visibility: hidden; opacity: 0; pointer-events: none; } /* Tooltip text styling */ [title]::after { content: attr(title); position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%) translateY(-5px); white-space: nowrap; z-index: 10; padding: 8px; border-radius: 4px; background-color: black; color: white; text-align: center; font-size: 14px; line-height: 1.2; transition: opacity 0.3s, visibility 0.3s; } /* Tooltip arrow */ [title]::before { content: ''; position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%) translateY(5px); border-width: 5px; border-style: solid; border-color: black transparent transparent transparent; transition: opacity 0.3s, visibility 0.3s; } /* Show tooltip on hover */ [title]:hover::before, [title]:hover::after { visibility: visible; opacity: 1; }
  18. /* Tooltip base styles for any element with a title

    attribute */ [title] { position: relative; cursor: pointer; display: inline-block; } /* Hidden before hover */ [title]::before, [title]::after { visibility: hidden; opacity: 0; pointer-events: none; } /* Tooltip text styling */ [title]::after { content: attr(title); position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%) translateY(-5px); white-space: nowrap; z-index: 10; padding: 8px; border-radius: 4px; background-color: black; color: white; text-align: center; font-size: 14px; line-height: 1.2; transition: opacity 0.3s, visibility 0.3s; } /* Tooltip arrow */ [title]::before { content: ''; position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%) translateY(5px); border-width: 5px; border-style: solid; border-color: black transparent transparent transparent; transition: opacity 0.3s, visibility 0.3s; } /* Show tooltip on hover */ [title]:hover::before, [title]:hover::after { visibility: visible; opacity: 1; } ... and the code fits on a slide "
  19. /* Tooltip base styles for any element with a title

    attribute */ [title] { position: relative; cursor: pointer; display: inline-block; } /* Hidden before hover */ [title]::before, [title]::after { visibility: hidden; opacity: 0; pointer-events: none; } /* Tooltip text styling */ [title]::after { content: attr(title); position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%) translateY(-5px); white-space: nowrap; z-index: 10; padding: 8px; border-radius: 4px; background-color: black; color: white; text-align: center; font-size: 14px; line-height: 1.2; transition: opacity 0.3s, visibility 0.3s; } /* Tooltip arrow */ [title]::before { content: ''; position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%) translateY(5px); border-width: 5px; border-style: solid; border-color: black transparent transparent transparent; transition: opacity 0.3s, visibility 0.3s; } /* Show tooltip on hover */ [title]:hover::before, [title]:hover::after { visibility: visible; opacity: 1; }
  20. /* Tooltip base styles for any element with a title

    attribute */ [title] { position: relative; cursor: pointer; display: inline-block; } /* Hidden before hover */ [title]::before, [title]::after { visibility: hidden; opacity: 0; pointer-events: none; } /* Tooltip text styling */ [title]::after { content: attr(title); position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%) translateY(-5px);
  21. /* Tooltip base styles for any element with a title

    attribute */ [title] { position: relative; cursor: pointer; display: inline-block; } /* Hidden before hover */ [title]::before, [title]::after { visibility: hidden; opacity: 0; pointer-events: none; } /* Tooltip text styling */ [title]::after { content: attr(title); position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%) translateY(-5px); white-space: nowrap;
  22. pointer-events: none; } /* Tooltip text styling */ [title]::after {

    content: attr(title); position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%) translateY(-5px); white-space: nowrap; z-index: 10; padding: 8px; border-radius: 4px; background-color: black; color: white; text-align: center; font-size: 14px; line-height: 1.2; transition: opacity 0.3s, visibility 0.3s; } /* Tooltip arrow */ [title]::before {
  23. line-height: 1.2; transition: opacity 0.3s, visibility 0.3s; } /* Tooltip

    arrow */ [title]::before { content: ''; position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%) translateY(5px); border-width: 5px; border-style: solid; border-color: black transparent transparent transparent; transition: opacity 0.3s, visibility 0.3s; } /* Show tooltip on hover */ [title]:hover::before, [title]:hover::after { visibility: visible; opacity: 1; }
  24. https://codepen.io/web-dot-dev/pen/gbOKyRZ <select> <button> <div> <selectedcontent> <div class="custom-option"> <span class="indicator success"></span>

    <span class="option-text">On</span> </div> </selectedcontent> <svg width="24" height="24" viewBox="0 0 24 24"> <path fill="currentColor" d="m7 10l5 5l5-5z"></path> </svg> </div> </button> <div> <option value="on"> <div class="custom-option"> <span class="indicator success"></span> <span class="option-text">On</span> </div> </option> <option value="off"> <div class="custom-option"> <span class="indicator danger"></span> <span class="option-text">Off</span> </div> </option> </div> </select>