Inline SVG Social Icon Bar No Icon Fonts
Published
20 hand-coded CSS social buttons for blogs, SaaS marketing pages, e-commerce product pages, creator bio pages and support widgets. Covers share and follow controls, the Web Share API with a working fallback menu, prefilled intent URLs, live share counts, standalone sign-in button sets, Linktree-style link stacks and direct-message contact cards. Brand marks are inline SVG with no icon font and no external request. Scoped under .soc-NN for no-collision pasting, prefers-reduced-motion guarded, framework-agnostic.
Related34 CSS Floating Buttons25 CSS Footer Designs30 CSS Login Forms20 CSS Copy Buttons
Published

Published
Published
Published
Published

Published

Published

Published

Published

Published

Published

Published

Published

Published

Published

Published

Published

Published

Published

Published
fill="currentColor" and it inherits whatever colour the link already has, so hover and focus states need no extra rules. One caveat catches people: currentColor only inherits if the path does not hard-code its own fill, and most copied marks do, so strip any fill="#1DA1F2" from the path before wondering why your hover colour does nothing. Set the brand colour once as a custom property on each item — style="--brand:#0a66c2" — and a single shared rule can tint every channel differently. Mark the SVG aria-hidden="true" and put the accessible name on the link, or a screen reader announces nothing at all.aria-label="Follow us on LinkedIn" on the link, or visually-hidden text inside it. Prefer the hidden text if you also want the label to survive translation tools, which sometimes skip attributes. The visually-hidden utility must use the clip-path pattern rather than display:none or visibility:hidden — both of those remove the element from the accessibility tree entirely, which is the opposite of what you want. The second common failure is size. An icon-only control is frequently drawn at 24px, but WCAG 2.5.8 asks for a 24px minimum and 44px is the practical target on touch; pad the link rather than scaling the glyph so the icon stays crisp while the hit area grows. Finally, never remove the focus ring without replacing it — outline:none on a social row is the single most common keyboard regression in this pattern.navigator.share({ title, text, url }) opens the operating system's own share sheet, which is why it feels native on mobile and why it can reach apps your page knows nothing about. It returns a promise, so wrap it in try/catch and treat a rejection as ordinary — a user dismissing the sheet rejects with an AbortError, which is not a failure worth reporting. Three constraints decide whether you can call it at all. It requires a secure context, so HTTPS or localhost. It requires a genuine user gesture, so calling it from a timer, on page load, or after an await that breaks the gesture chain will throw. And desktop support is uneven, so a fallback is not optional. Feature-detect with if (navigator.share) and fall back to your own menu of channel links built on intent URLs. Do not detect by user agent; the capability varies by browser and context, not by device class.text and url, LinkedIn reads url, Facebook reads u, and Reddit reads title and url. Every value must be passed through encodeURIComponent separately — encoding the whole query string at once double-encodes the ampersands and the platform silently drops everything after the first parameter, which is the usual reason a share arrives with a title and no link. Two details matter for safety and behaviour. Any link with target="_blank" needs rel="noopener", or the opened page gets a reference to your window through window.opener and can navigate it. And if you open the composer with script instead of a link, pop-up blockers will stop the call unless it happens directly inside a click handler.font-variant-numeric: tabular-nums on the badge. By default most proportional fonts draw a 1 much narrower than a 0, so a counter ticking from 1,099 to 1,100 visibly reflows and the whole button twitches. Tabular figures give every digit the same advance width, so the number changes without the layout moving. Pair it with font-feature-settings: 'tnum' 1 if you need to cover older rendering paths. Two related traps show up in the same component. If you animate a pulse on increment by removing and re-adding a class in the same frame, the animation will not restart — the browser has not finished a style recalculation, so force a reflow or wait for the next requestAnimationFrame before re-adding. And if the count can grow by an order of magnitude, reserve the width with min-inline-size in ch units rather than letting the badge resize when the first four-digit number arrives.data-state of idle or following on the button drives every visual difference through attribute selectors, and aria-pressed carries the same state to assistive technology so the change is announced rather than merely seen. The detail that separates a polished build from a janky one is width. Swapping the label with textContent resizes the button and shoves whatever sits next to it, so stack both labels in a single grid cell — grid-area: 1 / 1 on each — and crossfade opacity between them. The button then keeps one width for every state. Real products also show a destructive affordance: hovering Following reveals Unfollow in red. Declare that on :focus-visible as well as :hover, or the option simply does not exist for keyboard users. Keep the revert honest — if the network call fails, put the state back rather than leaving an optimistic Following that lies about what the server knows.backdrop-filter stops working when an ancestor combines overflow: hidden with a transform, because that ancestor creates a containing block the filter cannot sample through. Nothing errors; the blur just vanishes. Always declare a solid background first and add the glass behind @supports (backdrop-filter: blur(1px)), or unsupported browsers render near-invisible buttons over a photo. For an animated gradient border, the usual failure is that the rotation does nothing at all: a bare custom property is just a string to the browser, so it cannot be interpolated. Register it first with @property --angle declaring syntax: '<angle>', an initial value and inherits: false, and the same keyframes suddenly animate. The registration must sit at the top level of the stylesheet, not nested inside a selector block..soc-NN selector and custom property is framework-agnostic, and the fourteen pure-CSS demos need no JavaScript in any framework. Where behaviour exists, the shape is the same everywhere: one piece of state plus a small handler. In React a follow toggle is const [following, setFollowing] = useState(false) driving a data-state attribute, and any success-window timer must be cleared in the effect cleanup or a rapid re-click leaves a stale timeout that resets the label early. Vue uses a ref with onBeforeUnmount; Svelte a plain let and the cleanup returned from onMount. One trap is specific to server-rendered frameworks like Next and Nuxt: navigator.share and navigator.clipboard do not exist during the server pass, so feature-detect inside an effect or an event handler rather than in the component body, which would otherwise throw a reference error at build time. For Tailwind, the brand colour custom property survives as an arbitrary value and the states map to data-[state=following]: variants.30 hand-coded CSS badges for status indicators, notifications, membership tiers, live-data displays, and SEO / DevOps / financial dashboards — upload progress, typing indicator, transit line status, Core Web Vitals, ECG heartbeat, CI/CD build pipeline, countdown ring, live price ticker, keycap shortcut, wax seal, conference lanyard, and holographic collectibles. Copy-paste HTML and CSS, WCAG 2.2 accessible, MIT licensed.
20 hand-coded CSS banner and alert bars for e-commerce storefronts, SaaS dashboards, marketing sites, and compliance-bound products. Covers GDPR cookie consent with a real preferences panel, promo bars with countdown timers, free-shipping threshold progress, app-install smart banners, maintenance and incident status bars, newsletter signup bars, age verification gates, limited-stock urgency banners, live event announcements, browser upgrade notices, geo and currency switchers, sticky top announcement bars, bottom cookie bars, inline form validation alerts, icon-aligned alert banners, left-border accent alerts, diagonal stripe promos, full-width hero banners, animated gradient border alerts, and a text-wrapping laboratory that shows five strategies for the unbreakable string that breaks more banners than anything else. Every bar is scoped under a .ba-NN prefix for no-collision pasting, guards prefers-reduced-motion, carries the correct aria-live and role semantics, and ports unchanged to React, Vue, Svelte, Astro, Next.js and Tailwind.
25 hand-coded CSS blockquote designs for SaaS testimonials, editorial pull quotes, documentation callouts, and developer engineering blogs: large decorative quotation marks with ::before / ::after glyphs, Tailwind CSS blockquote component, pure CSS callout / admonition boxes for Docusaurus / Mintlify / Nextra documentation, responsive center-aligned quote banners, modern minimalist left-border editorial style, animated CSS gradient border, classic left border, brutalist high-contrast, glassmorphism frosted card, glowing neon border, article pull quote with text-wrap, speech bubble chat-style, thick vertical accent rail, customer testimonial cards with avatar and star rating, inline highlighted text, marker highlight underline, floating drop-shadow, aurora gradient background, Twitter / X card style, multi-column newspaper editorial, IDE code-comment style, Markdown-compatible defaults, JavaScript testimonial quote slider, expandable read-more, and one-click copy button. 22 Pure CSS + 3 Light JS (slider, expand, copy). Every design scoped under .bq-NN prefix for no-collision pasting, prefers-reduced-motion guarded per WCAG 2.3.3, WCAG 2.2 AA accessible, framework-agnostic (React, Vue, Svelte, Astro, Next.js, Nuxt, Remix, SvelteKit).