emblaze's profile picture

Published by

published
updated

Category: Web, HTML, Tech

add interactive <input>s to your profile & posts (CSS hack)

SpaceHey doesn't let you use <input> elements, but there's ways to (mostly) workaround this.

The <input> element comes in many different types, and at first blush they're all totally useless without any JS or a <form> (which is also banned), but actually there are some cool CSS things you can do with them - like switching between themes or toggling things on and off.

But if you try to use an <input> element, SpaceHey will silently delete it when you save your profile/post. This actually happens for the majority of tags (you can see which a list of the few that are allowed when you go to edit your profile). The only forms of interaction we have access to are:

  • <a> elements let us click links
  • <details> (& <summary>) elements let us show and hide a section of content
  • <iframe> elements let us embed stuff from other sites, which can be very interactive, but we can only use a handful of music & video websites, and we can't use our own styling.

Pointless Buttons - hovering

Not all hope is lost! CSS has the :hover and :active psuedoclasses that let us detect mouse position and clicking. kinda. It's not much, but we can recreate a <button> (or a <input type="button">) Like this!. It doesn't do anything... but still. looks nice.

Here's the code I used for that:

<span class="button">Like this!</span>
Button HTMLButton CSS
.button { background: rgb(233, 233, 237); padding: 2px 4px; border-radius: 0.25em; border: solid 1px #888; width: fit-content; margin-bottom: 0.5em; display: inline-block;
          cursor: default; -webkit-touch-callout: none; -webkit-user-select: none; select: none; font-size: 0.825rem; font-weight: normal; }
.button:hover { background: rgb(208, 208, 215); border-color: #777; }
.button:active { background: rgb(177, 177, 185); border-color: #666; }

Checkboxes - toggling

What if we want to remember after a click? :active only targets elements that are currently being pressed. Usually we'd use <input type="checkbox"> for something we can toggle. Luckily <details> provides the same thing, just replace any :checked selectors with :open.

By default a <details> element looks like this:


To style it, we need to put a <summary> element inside it and style that instead (anything else inside will be hidden when it's closed). We can write <details><summary>text</summary></details> as the equivalent of <label><input type="checkbox">text</label> (with a bit of styling). See:

Toggle me!

<details class="checkbox"><summary>text</summary></details>
<br/>
Checkbox HTMLCheckbox CSS
details.checkbox { display: inline; }
details.checkbox summary { list-style: none; cursor: default; }
details.checkbox summary::before { width: 14px; height: 14px; display: inline-block; content: "";  margin: 0 3px 0 4px; position: relative; top: 2px; }

details.checkbox summary::before { background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 32 32' id='icon' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%23666' width='32' height='32' rx='5' /%3E%3Crect fill='white' x='2' y='2' width='28' height='28' rx='2'/%3E%3C/svg%3E"); }
details.checkbox summary:hover::before { background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 32 32' id='icon' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%23333' width='32' height='32' rx='5' /%3E%3Crect fill='white' x='2' y='2' width='28' height='28' rx='2'/%3E%3C/svg%3E"); }
details.checkbox:open summary::before { background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 32 32' id='icon' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%23253ddb' x='1' y='1' width='30' height='30' rx='3' /%3E%3Cpath d='M5,17 L8,14 L12,18 L24,6 L27,9 L12,24 Z' fill='white'/%3E%3C/svg%3E"); }
details.checkbox:open summary:hover::before { background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 32 32' id='icon' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%233061e8' x='1' y='1' width='30' height='30' rx='3' /%3E%3Cpath d='M5,17 L8,14 L12,18 L24,6 L27,9 L12,24 Z' fill='white'/%3E%3C/svg%3E"); }

Radio buttons - choosing

Another super useful input type is 'radio buttons', which let you select one option in a group. Unfortunately the trusty <details> fails us here, if we have more than two options there's no way to turn one off and another on in a single click.

The next best thing is using an <a> element. If we have an element with an id="..." attribute, then we can link to it (without refreshing the page!) (just set href="#..." on an <a>), and we can tell when we've clicked on such a link using the :target selector. The downside is that we won't be able to have multiple radio groups in the same page.

Option 1
Option 2
Option 3
<!-- You can use any tag for these, but if they're not hidden, you'll jump around the page when you select the radio buttons -->
<a class="hide" id="option1"></a>
<a class="hide" id="option2"></a>
<a class="hide" id="option3"></a>

<a class="radio" href="#option1">Option 1</a> 
<br/>
<a class="radio" href="#option2">Option 2</a>
<br/>
<a class="radio" href="#option3">Option 3</a>
Radio buttons HTMLRadio buttons CSS
.hide { display: none; }
/* remove link styling */
.radio, .radio:hover, .radio:active {
  cursor: default;
  color: inherit;
  text-decoration: inherit
}
/* add indicators */
.radio::before { width: 16px; height: 16px; display: inline-block; content: "";  margin: 0 3px 0 4px; position: relative; top: 1px; }
.radio::before { background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 32 32' id='icon' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle fill='%23fff' stroke-width='2' stroke='%23888' cx='16' cy='18' r='13'/%3E%3C/svg%3E") }
.radio:hover::before { background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 32 32' id='icon' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle fill='%23fff' stroke-width='2' stroke='%23555' cx='16' cy='18' r='13'/%3E%3C/svg%3E") }
.radio:active::before { background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 32 32' id='icon' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle fill='%23fff' stroke-width='2' stroke='%23333' cx='16' cy='18' r='13'/%3E%3C/svg%3E") }
#option1:target ~ .radio[href="#option1"]::before, 
#option2:target ~ .radio[href="#option2"]::before, 
#option3:target ~ .radio[href="#option3"]::before { background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 32 32' id='icon' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle fill='%23fff' stroke-width='2' stroke='%2300f' cx='16' cy='18' r='13'/%3E%3Ccircle fill='%2335e' cx='16' cy='18' r='8'/%3E%3C/svg%3E") }

If all you need is a single input that you can't uncheck (like a radio button that's alone in its group), then you can just hide the <summary> once it's clicked.

Text - freeform input

What if you want somewhere you can type? There's some cool & unique (though limited) things you can do if you have a <input type="text"> with a custom pattern attribute using the :valid selector. Imagine: a section of your page only 'unlocks' if you type in the magic word (or just you look at the source code :P ). Unfortunately we can't do any of that, in fact letting you type at all is a real challenge.

As far as I can tell there are three ways to make a website typeable:

  1. Use an <input> element – which obviously isn't an option here
  2. Use a <textarea> element – but this gets removed just like <input>
  3. Add the contenteditable attribute to any element – this is my absolute favourite thing in all of HTML, but unfortunately SpaceHey removes it too.

All three of this options seem impossible. So is it just totally impossible? well, no ‐ if it was why then would I bother writing this section ;P. But we're gonna have to get desperate. If we can't add any of these, maybe we can just repurpose an existing one? Well as luck would have it, there is one <input type="text"> element already on the page - the search bar!

Things get a little complicated for two reasons though: first, the search bar is nested all the way up in the <nav> and we can't move it - if we want it to show up somewhere else we'll have to position it manually, and second, spacehey tells us to not "hide the Navigation bar (Including the SpaceHey Logo, Search, LogIn/LogOut Actions and Links)", so if we move the search bar we'll have to put it back too.

If your screen is too narrow, there'll be less words per line, so I won't be able to predict exactly how many lines down this text is. So I've set this example to only display if your screen is wide enough - sorry if you're on mobile. It'll probably still work a little strange on big screens, if you really want a text input I'd recommend putting it as part of a fake 'pop-up' that's always in the same position & only move the input when the popup is opened.

With that said, here's the input:


Text input CSS
@media (min-width: 810px) {
 /* move the input. if you want this to be in-line with text, make sure you set a custom font */
  nav .search-wrapper input { position: absolute; left: 363px; top: 2175px; z-index: 9; }
 /* put a fake input box in its place */
  nav .search-wrapper::after { width: 156px; height: 21px; background-color: white; display: block; content: ""; border: solid 1px rgb(143, 143, 157); }
 /* move the input back when we hover over the nav, or click on the fake box (mobile has no hover) */
  nav:hover:not(:has(input:hover)) .search-wrapper input, nav .search-wrapper:active input:not(:active)  { position: revert; }
  nav:hover:not(:has(input:hover)) .search-wrapper::after, nav .search-wrapper:active:not(:has(input:active))::after { display: none; }
}

Other stuff / using iframes

That's all the input types that I can hack a substitute to. But I haven't tried using any <iframe>s, that's because you can't target, change, or respond to anything that happens an iframe using just HTML & CSS, you're stuck with whatever the embedded website provides and you can only use one of the 19 whitelisted websites. If it can't effect the style of anything else, I don't really see the point of having an embedded input.

But there is a good chance you can emulate (or just directly use) other <input> types by using an iframe. (like maybe you can get a slidey widget working.. I can imagine that adding to the vibe of a playful layout). If you do manage to hack anything together pls leave a comment! For a place to start: spacehey lets you use hearthis.at embeds which can load css from a custom url.


Wew.. that was a long post. congrats on making it to the end!

I hope u found this helpful! Feel free to ask if ur confused ab anything & lmk if you end up using any of these hehe


19 Kudos

Comments

Displaying 0 of 0 comments ( View all | Add Comment )