aboutsummaryrefslogtreecommitdiff
path: root/build/posts/easy-custom-radio-inputs/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'build/posts/easy-custom-radio-inputs/index.html')
-rw-r--r--build/posts/easy-custom-radio-inputs/index.html217
1 files changed, 0 insertions, 217 deletions
diff --git a/build/posts/easy-custom-radio-inputs/index.html b/build/posts/easy-custom-radio-inputs/index.html
deleted file mode 100644
index 9936801..0000000
--- a/build/posts/easy-custom-radio-inputs/index.html
+++ /dev/null
@@ -1,217 +0,0 @@
-<!doctype html>
-<html lang="en">
-<head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <meta name="color-scheme" content="dark light">
- <link rel="icon" href="data:,">
- <title>Easy Custom Radio Inputs</title>
- <link href="/atom.xml" type="application/atom+xml" rel="alternate" title="Atom feed for blog posts" />
- <link href="/rss.xml" type="application/rss+xml" rel="alternate" title="RSS feed for blog posts" />
-<style>*{box-sizing:border-box;}body{font-family:sans-serif;line-height:1.33;margin:0 auto;max-width:650px;padding:1rem;}blockquote{background:rgba(0,0,0,0.1);border-left:4px solid;padding-left:5px;}img{max-width:100%;}pre{border:1px solid;overflow:auto;padding:5px;}table{text-align:left;width:100%;}.footnotes{font-size:90%;}</style>
-</head>
-
-<nav>
- <a href="#menu">Menu &darr;</a>
-</nav>
-
-<main>
-<h1 id="easy-custom-radio-inputs">Easy Custom Radio Inputs</h1>
-<p>2019-01-21</p>
-<p>Default radio inputs are notoriously horrible looking and are something designers tend to over-think when trying to customize them. Let&#8217;s walk through how to create custom radio buttons with <em>pure CSS</em>, while still preserving performance and accessibility.</p>
-<h2 id="the-final-product">The Final Product</h2>
-<p>This is what we will be designing:</p>
-<p><img src="/public/images/custom-radio-inputs.png" alt="Custom radio inputs" /></p>
-<p><a href="https://codepen.io/bradleytaunt/pen/oNjwMyX">Live CodePen Example</a></p>
-<hr/>
-<h2 id="the-bones-of-our-radio-inputs-html">The bones of our radio inputs (HTML)</h2>
-<pre><code>&#60;input class="radio-btn" name="radio-collection" id="radio-1" type="radio"&#62;
-&#60;label class="radio-label" for="radio-1"&#62;&#60;span&#62;I am very satisfied&#60;&#47;span&#62;&#60;&#47;label&#62;
-
-&#60;input class="radio-btn" name="radio-collection" id="radio-2" type="radio"&#62;
-&#60;label class="radio-label" for="radio-2"&#62;&#60;span&#62;I am satisfied&#60;&#47;span&#62;&#60;&#47;label&#62;
-
-&#60;input class="radio-btn" name="radio-collection" id="radio-3" type="radio"&#62;
-&#60;label class="radio-label" for="radio-3"&#62;&#60;span&#62;I am indifferent&#60;&#47;span&#62;&#60;&#47;label&#62;
-
-&#60;input class="radio-btn" name="radio-collection" id="radio-4" type="radio"&#62;
-&#60;label class="radio-label" for="radio-4"&#62;&#60;span&#62;I am unsatisfied&#60;&#47;span&#62;&#60;&#47;label&#62;
-
-&#60;input class="radio-btn" name="radio-collection" id="radio-5" type="radio"&#62;
-&#60;label class="radio-label" for="radio-5"&#62;&#60;span&#62;I am very unsatisfied&#60;&#47;span&#62;&#60;&#47;label&#62;
-</code></pre>
-<p>I know it looks like a lot is going on here, but it&#8217;s pretty straightforward so let&#8217;s unpackage line by line:</p>
-<h3 id="radio-inputs">Radio inputs</h3>
-<pre><code>&#60;input class="radio-btn" name="radio-collection" id="radio-1" type="radio"&#62;
-</code></pre>
-<p>This is the default <code>radio</code> input. We give it:</p>
-<ul>
-<li>a <code>name</code> (inputs with a shared <code>name</code> are grouped together)</li>
-<li>an <code>id</code> (so our label can target this input)</li>
-<li>a <code>class</code> (so we can style it later)</li>
-</ul>
-<p><strong>Important</strong>: be sure to have a unique <code>id</code> for each input so your labels don&#8217;t end up connected to multiple radios. In this demo we are simply incrementing them by one.</p>
-<h3 id="labels">Labels</h3>
-<p>Adding the labels is fairly straightforward, we just include the corresponding input&#8217;s <code>id</code> in the label&#8217;s <code>for</code> attribute. The label content is wrapped in a <code>span</code> - which I will explain the reasoning for later.</p>
-<p>For styling purposes we also add the <code>radio-label</code> class.</p>
-<pre><code>&#60;label class="radio-label" for="radio-1"&#62;&#60;span&#62;I am very satisfied&#60;&#47;span&#62;&#60;&#47;label&#62;
-</code></pre>
-<p>This is looking pretty terrible - but that&#8217;s nothing some good ol&#8217; CSS can&#8217;t fix!</p>
-<h2 id="the-flesh-of-our-radio-inputs-css">The flesh of our radio inputs (CSS)</h2>
-<p>First we give some basic styling to our <code>label</code> and <code>input</code> classes (along with hover states). The <code>radio</code> element is actually hidden from view, but by using the <code>visibility</code> attribute we still keep it accessible for screen-readers.</p>
-<pre><code>.radio-label {
- background: white;
- border: 1px solid #eee;
- border-radius: 5px;
- box-shadow: 0 2px 4px rgba(0,0,0,0.05);
- cursor: pointer;
- display: inline-block;
- font-weight: 600;
- margin: 0 auto 10px;
- &#47;* This 65px padding makes room for the custom input *&#47;
- padding: 20px 20px 20px 65px;
- position: relative;
- transition: .3s ease all;
- width: 100%;
-}
-.radio-label:hover {
- box-shadow: 0 4px 8px rgba(0,0,0,0.05);
-}
-.radio-btn {
- position: absolute;
- visibility: hidden;
-}
-</code></pre>
-<p>Remember that <code>span</code> element inside the label? We set it&#8217;s <code>user-select</code> property to <code>none</code> so we avoid any possible issue with the user selecting the text on-click:</p>
-<pre><code>.radio-label span {
- -webkit-user-select: none;
- -moz-user-select: none;
- user-select: none;
-}
-</code></pre>
-<p>Next we include the default empty selection element (to mimic the original radio input) via a pseudo element:</p>
-<pre><code>.radio-label:before {
- background: #eee;
- border-radius: 50%;
- content:&#39;&#39;;
- height: 30px;
- left: 20px;
- position: absolute;
- &#47;* Half the height of it&#39;s parent minus half of it&#39;s own height *&#47;
- top: calc(50% - 15px);
- transition: .3s ease background-color;
- width: 30px;
-}
-</code></pre>
-<h2 id="a-few-final-steps">A Few Final Steps</h2>
-<p>The final step is adding the custom styling for when an <code>input</code> item is selected (<code>:checked</code>).</p>
-<p>You will notice the use of a <code>base64</code> element for the custom checkmark - feel free to subsitute this for an actual image or none at all (this is just my personal design preference).</p>
-<pre><code>.radio-btn:checked + .radio-label {
- background: #ECF5FF;
- border-color: #4A90E2;
-}
-.radio-btn:checked + .radio-label:before {
- background-color: #4A90E2;
- background-image: url(&#39;data:image&#47;svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIyNiIgaGVpZ2h0PSIyMCIgdmVyc2lvbj0iMS4xIiB2aWV3Qm94PSIyLjAyOTY4IC00MC4wOTAzIDI2IDIwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48IS0tR2VuZXJhdGVkIGJ5IElKU1ZHIChodHRwczovL2dpdGh1Yi5jb20vaWNvbmphci9JSlNWRyktLT48cGF0aCBkPSJNMjcuOTc0MywtMzYuMTI3MmMwLDAuNDQ2NDI4IC0wLjE1NjI1LDAuODI1ODkzIC0wLjQ2ODc1LDEuMTM4MzlsLTEyLjEyMDUsMTIuMTIwNWwtMi4yNzY3OSwyLjI3Njc5Yy0wLjMxMjUsMC4zMTI1IC0wLjY5MTk2NCwwLjQ2ODc1IC0xLjEzODM5LDAuNDY4NzVjLTAuNDQ2NDI4LDAgLTAuODI1ODkzLC0wLjE1NjI1IC0xLjEzODM5LC0wLjQ2ODc1bC0yLjI3Njc5LC0yLjI3Njc5bC02LjA2MDI3LC02LjA2MDI3Yy0wLjMxMjUsLTAuMzEyNSAtMC40Njg3NSwtMC42OTE5NjUgLTAuNDY4NzUsLTEuMTM4MzljMCwtMC40NDY0MjkgMC4xNTYyNSwtMC44MjU4OTMgMC40Njg3NSwtMS4xMzgzOWwyLjI3Njc5LC0yLjI3Njc5YzAuMzEyNSwtMC4zMTI1IDAuNjkxOTY1LC0wLjQ2ODc1IDEuMTM4MzksLTAuNDY4NzVjMC40NDY0MjksMCAwLjgyNTg5MywwLjE1NjI1IDEuMTM4MzksMC40Njg3NWw0LjkyMTg4LDQuOTM4NjJsMTAuOTgyMSwtMTAuOTk4OWMwLjMxMjUsLTAuMzEyNSAwLjY5MTk2NCwtMC40Njg3NSAxLjEzODM5LC0wLjQ2ODc1YzAuNDQ2NDI4LDAgMC44MjU4OTMsMC4xNTYyNSAxLjEzODM5LDAuNDY4NzVsMi4yNzY3OCwyLjI3Njc5YzAuMzEyNSwwLjMxMjUgMC40Njg3NSwwLjY5MTk2NCAwLjQ2ODc1LDEuMTM4MzlaIiB0cmFuc2Zvcm09InNjYWxlKDEuMDAxOTgpIiBmaWxsPSIjZmZmIj48L3BhdGg+PC9zdmc+&#39;);
- background-repeat: no-repeat;
- background-position: center;
- background-size: 15px;
-}
-</code></pre>
-<p><strong>And that&#8217;s it.</strong></p>
-<p>For easier reference the entire CSS file can be found below:</p>
-<pre><code>.radio-label {
- background: white;
- border: 1px solid #eee;
- border-radius: 5px;
- box-shadow: 0 2px 4px rgba(0,0,0,0.05);
- cursor: pointer;
- display: inline-block;
- font-weight: 600;
- margin: 0 auto 10px;
- padding: 20px 20px 20px 65px;
- position: relative;
- transition: .3s ease all;
- width: 100%;
-}
-.radio-label:hover {
- box-shadow: 0 4px 8px rgba(0,0,0,0.05);
-}
-.radio-label:before {
- background: #eee;
- border-radius: 50%;
- content:&#39;&#39;;
- height: 30px;
- left: 20px;
- position: absolute;
- top: calc(50% - 15px);
- transition: .3s ease background-color;
- width: 30px;
-}
-.radio-label span {
- -webkit-user-select: none;
- -moz-user-select: none;
- user-select: none;
-}
-.radio-btn {
- position: absolute;
- visibility: hidden;
-}
-.radio-btn:checked + .radio-label {
- background: #ECF5FF;
- border-color: #4A90E2;
-}
-.radio-btn:checked + .radio-label:before {
- background-color: #4A90E2;
- background-image: url(&#39;data:image&#47;svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIyNiIgaGVpZ2h0PSIyMCIgdmVyc2lvbj0iMS4xIiB2aWV3Qm94PSIyLjAyOTY4IC00MC4wOTAzIDI2IDIwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48IS0tR2VuZXJhdGVkIGJ5IElKU1ZHIChodHRwczovL2dpdGh1Yi5jb20vaWNvbmphci9JSlNWRyktLT48cGF0aCBkPSJNMjcuOTc0MywtMzYuMTI3MmMwLDAuNDQ2NDI4IC0wLjE1NjI1LDAuODI1ODkzIC0wLjQ2ODc1LDEuMTM4MzlsLTEyLjEyMDUsMTIuMTIwNWwtMi4yNzY3OSwyLjI3Njc5Yy0wLjMxMjUsMC4zMTI1IC0wLjY5MTk2NCwwLjQ2ODc1IC0xLjEzODM5LDAuNDY4NzVjLTAuNDQ2NDI4LDAgLTAuODI1ODkzLC0wLjE1NjI1IC0xLjEzODM5LC0wLjQ2ODc1bC0yLjI3Njc5LC0yLjI3Njc5bC02LjA2MDI3LC02LjA2MDI3Yy0wLjMxMjUsLTAuMzEyNSAtMC40Njg3NSwtMC42OTE5NjUgLTAuNDY4NzUsLTEuMTM4MzljMCwtMC40NDY0MjkgMC4xNTYyNSwtMC44MjU4OTMgMC40Njg3NSwtMS4xMzgzOWwyLjI3Njc5LC0yLjI3Njc5YzAuMzEyNSwtMC4zMTI1IDAuNjkxOTY1LC0wLjQ2ODc1IDEuMTM4MzksLTAuNDY4NzVjMC40NDY0MjksMCAwLjgyNTg5MywwLjE1NjI1IDEuMTM4MzksMC40Njg3NWw0LjkyMTg4LDQuOTM4NjJsMTAuOTgyMSwtMTAuOTk4OWMwLjMxMjUsLTAuMzEyNSAwLjY5MTk2NCwtMC40Njg3NSAxLjEzODM5LC0wLjQ2ODc1YzAuNDQ2NDI4LDAgMC44MjU4OTMsMC4xNTYyNSAxLjEzODM5LDAuNDY4NzVsMi4yNzY3OCwyLjI3Njc5YzAuMzEyNSwwLjMxMjUgMC40Njg3NSwwLjY5MTk2NCAwLjQ2ODc1LDEuMTM4MzlaIiB0cmFuc2Zvcm09InNjYWxlKDEuMDAxOTgpIiBmaWxsPSIjZmZmIj48L3BhdGg+PC9zdmc+&#39;);
- background-repeat: no-repeat;
- background-position: center;
- background-size: 15px;
-}
-</code></pre>
-<hr/>
-<h2 id="but-wait---we-can-get-even-fancier">But wait - we can get even fancier!</h2>
-<p>Since this demo is based off a survey-type questionaire, wouldn&#8217;t it be interesting to give the different selectable options their own styling based on their context? Take a look at the further customized version below:</p>
-<p>We can do so by adding <code>positive</code>, <code>neutral</code> and <code>negative</code> class names to the radio inputs with their own respective properties:</p>
-<pre><code>.radio-btn.positive:checked + .radio-label {
- background: #EAFFF6;
- border-color: #32B67A;
-}
-.radio-btn.positive:checked + .radio-label:before {
- background-color: #32B67A;
-}
-.radio-btn.neutral:checked + .radio-label:before {
- background-image: url(&#39;data:image&#47;svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAtMTUgMzAgOC41NzE0MyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+PCEtLUdlbmVyYXRlZCBieSBJSlNWRyAoaHR0cHM6Ly9naXRodWIuY29tL2ljb25qYXIvSUpTVkcpLS0+PHBhdGggZD0iTTMwLC0xMi4zMjE0djMuMjE0MjljMCwwLjczNjYwNyAtMC4yNjIyNzcsMS4zNjcxOSAtMC43ODY4MywxLjg5MTc0Yy0wLjUyNDU1NCwwLjUyNDU1NCAtMS4xNTUxMywwLjc4NjgzMSAtMS44OTE3NCwwLjc4NjgzMWgtMjQuNjQyOWMtMC43MzY2MDcsMCAtMS4zNjcxOSwtMC4yNjIyNzcgLTEuODkxNzQsLTAuNzg2ODMxYy0wLjUyNDU1MywtMC41MjQ1NTMgLTAuNzg2ODMsLTEuMTU1MTMgLTAuNzg2ODMsLTEuODkxNzR2LTMuMjE0MjljMCwtMC43MzY2MDcgMC4yNjIyNzcsLTEuMzY3MTkgMC43ODY4MywtMS44OTE3NGMwLjUyNDU1NCwtMC41MjQ1NTMgMS4xNTUxMywtMC43ODY4MyAxLjg5MTc0LC0wLjc4NjgzaDI0LjY0MjljMC43MzY2MDcsMCAxLjM2NzE5LDAuMjYyMjc3IDEuODkxNzQsMC43ODY4M2MwLjUyNDU1MywwLjUyNDU1NCAwLjc4NjgzLDEuMTU1MTMgMC43ODY4MywxLjg5MTc0WiIgZmlsbD0iI2ZmZiI+PC9wYXRoPjwvc3ZnPg==&#39;);
-}
-.radio-btn.negative:checked + .radio-label {
- background: #FFF2F2;
- border-color: #E75153;
-}
-.radio-btn.negative:checked + .radio-label:before {
- background-color: #E75153;
- background-image: url(&#39;data:image&#47;svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgdmVyc2lvbj0iMS4xIiB2aWV3Qm94PSIxLjg1MTg1IC0zOS42OTcgMjAgMjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjwhLS1HZW5lcmF0ZWQgYnkgSUpTVkcgKGh0dHBzOi8vZ2l0aHViLmNvbS9pY29uamFyL0lKU1ZHKS0tPjxwYXRoIGQ9Ik0yMS43Mjk5LC0yMy40NzFjMCwwLjQ0NjQyOCAtMC4xNTYyNSwwLjgyNTg5MyAtMC40Njg3NSwxLjEzODM5bC0yLjI3Njc5LDIuMjc2NzljLTAuMzEyNSwwLjMxMjUgLTAuNjkxOTY0LDAuNDY4NzUgLTEuMTM4MzksMC40Njg3NWMtMC40NDY0MjgsMCAtMC44MjU4OTMsLTAuMTU2MjUgLTEuMTM4MzksLTAuNDY4NzVsLTQuOTIxODcsLTQuOTIxODhsLTQuOTIxODgsNC45MjE4OGMtMC4zMTI1LDAuMzEyNSAtMC42OTE5NjQsMC40Njg3NSAtMS4xMzgzOSwwLjQ2ODc1Yy0wLjQ0NjQyOCwwIC0wLjgyNTg5MiwtMC4xNTYyNSAtMS4xMzgzOSwtMC40Njg3NWwtMi4yNzY3OSwtMi4yNzY3OWMtMC4zMTI1LC0wLjMxMjUgLTAuNDY4NzUsLTAuNjkxOTY1IC0wLjQ2ODc1LC0xLjEzODM5YzAsLTAuNDQ2NDI5IDAuMTU2MjUsLTAuODI1ODkzIDAuNDY4NzUsLTEuMTM4MzlsNC45MjE4OCwtNC45MjE4OGwtNC45MjE4OCwtNC45MjE4OGMtMC4zMTI1LC0wLjMxMjUgLTAuNDY4NzUsLTAuNjkxOTY0IC0wLjQ2ODc1LC0xLjEzODM5YzAsLTAuNDQ2NDI4IDAuMTU2MjUsLTAuODI1ODkzIDAuNDY4NzUsLTEuMTM4MzlsMi4yNzY3OSwtMi4yNzY3OGMwLjMxMjUsLTAuMzEyNSAwLjY5MTk2NCwtMC40Njg3NSAxLjEzODM5LC0wLjQ2ODc1YzAuNDQ2NDI5LDAgMC44MjU4OTMsMC4xNTYyNSAxLjEzODM5LDAuNDY4NzVsNC45MjE4OCw0LjkyMTg4bDQuOTIxODcsLTQuOTIxODhjMC4zMTI1LC0wLjMxMjUgMC42OTE5NjUsLTAuNDY4NzUgMS4xMzgzOSwtMC40Njg3NWMwLjQ0NjQyOSwwIDAuODI1ODkzLDAuMTU2MjUgMS4xMzgzOSwwLjQ2ODc1bDIuMjc2NzksMi4yNzY3OGMwLjMxMjUsMC4zMTI1IDAuNDY4NzUsMC42OTE5NjUgMC40Njg3NSwxLjEzODM5YzAsMC40NDY0MjkgLTAuMTU2MjUsMC44MjU4OTMgLTAuNDY4NzUsMS4xMzgzOWwtNC45MjE4OCw0LjkyMTg4bDQuOTIxODgsNC45MjE4OGMwLjMxMjUsMC4zMTI1IDAuNDY4NzUsMC42OTE5NjQgMC40Njg3NSwxLjEzODM5WiIgdHJhbnNmb3JtPSJzY2FsZSgxLjAwNTYxKSIgZmlsbD0iI2ZmZiI+PC9wYXRoPjwvc3ZnPg==&#39;);
-}
-</code></pre>
-<p>I hope this shows new designers that simple custom radio inputs aren&#8217;t so hard to implement after-all and can actually be pretty fun to design.</p>
-<footer role="contentinfo">
- <h2>Menu Navigation</h2>
- <ul id="menu">
- <li><a href="/">Home</a></li>
- <li><a href="/projects">Projects</a></li>
- <li><a href="/uses">Uses</a></li>
- <li><a href="/wiki">Wiki</a></li>
- <li><a href="/resume">Resume</a></li>
- <li><a href="/colophon">Colophon</a></li>
- <li><a href="/now">Now</a></li>
- <li><a href="/donate">Donate</a></li>
- <li><a href="/atom.xml">RSS</a></li>
- <li><a href="#top">&uarr; Top of the page</a></li>
- </ul>
- <small>
- Built with <a href="https://barf.btxx.org">barf</a>. <br>
- Feeds: <a href="/atom.xml">Atom</a> & <a href="/rss.xml">RSS</a><br>
- Maintained with ♥ for the web. <br>
- Proud supporter of <a href="https://usefathom.com/ref/DKHJVX">Fathom</a> &amp; <a href="https://nextdns.io/?from=74d3p3h8">NextDNS</a>. <br>
- The content for this site is <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>.<br> The <a href="https://git.sr.ht/~bt/bt.ht">code for this site</a> is <a href="https://git.sr.ht/~bt/bt.ht/tree/master/item/LICENSE">MIT</a>.
- </small>
-</footer> \ No newline at end of file