0

I'm trying to create an accessible form that shows placeholder text, but moves it above the input when the user types into the input.

I've made a start by styling the label so it appears like a placeholder (sitting 'inside' the input through absolute positioning) and can move upon action. My problem is that I don't know if I'll be able to target the label through css.

I'm using contact form 7 on wordpress, so the form is generated. I can add wrapper elements (like the span for the label) but can't remove the span around the input. So a css rule like input ~ label will not work here.

Any advice for either a non-css workaround or an effective css way to target this? If possible I'd like to keep the 'label' tag so the form meets the accessibility criteria.

My code:

form.wpcf7-form p {
    position: relative;
    width: 100%;
    min-height: 1px;
    padding-right: 7.5px;
    padding-left: 7.5px;
    flex: 0 0 50%;
    max-width: 50%;
}

form.wpcf7-form p label {
    width: 100%;
    position: relative;
}

form.wpcf7-form p label span.formlabel {
    position: absolute;
    top: .8rem;
    z-index: 10;
    left: 1rem;
}

.form-control {
    display: block;
    width: 100%;
    padding: .8rem 0.75rem;
    font-size: 1rem;
    line-height: 1.5;
    color: #495057;
    background-color: #5D5D5D;
    background-clip: padding-box;
    border: none;
    border-radius: 0.25rem;
    transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}
<form method="post" class="wpcf7-form" novalidate="novalidate">

<p>
<label>
<span class="formlabel">Business Name</span>
<span class="wpcf7-form-control-wrap business-name">
<input type="text" name="business-name" value="" size="40" class="wpcf7-form-control wpcf7-text wpcf7-validates-as-required form-control" aria-required="true" aria-invalid="false">
</span> 
</label> 
</p>

<p>
<label> 
  <span class="formlabel">First Name</span>
  <span class="wpcf7-form-control-wrap first-name">
  <input type="text" name="first-name" value="" size="40"   class="wpcf7-form-control wpcf7-text wpcf7-validates-as-required form-control" aria-required="true" aria-invalid="false">
  </span> 
 </label> 
</p>

<p>
<label> 
<span class="formlabel">Last Name</span>
<span class="wpcf7-form-control-wrap last-name">
<input type="text" name="last-name" value="" size="40" class="wpcf7-form-control wpcf7-text wpcf7-validates-as-required form-control" aria-required="true" aria-invalid="false">
</span> 
</label> </p>

<p>
<label> 
  <span class="formlabel">Your Telephone</span>
  <span class="wpcf7-form-control-wrap your-tel">
<input type="tel" name="your-tel" value="" size="40" class="wpcf7-form-control wpcf7-text wpcf7-tel wpcf7-validates-as-required wpcf7-validates-as-tel form-control" aria-required="true" aria-invalid="false">
  </span> 
  </label> 
</p>

<p>
  <label> 
  <span class="formlabel">Your Email</span>
  <span class="wpcf7-form-control-wrap your-email">
  <input type="email" name="your-email" value="" size="40" class="wpcf7-form-control wpcf7-text wpcf7-email wpcf7-validates-as-required wpcf7-validates-as-email form-control" aria-required="true" aria-invalid="false">
  </span> 
  </label> 
 </p>


<p><input type="submit" value="Place your request" class="wpcf7-form-control wpcf7-submit btn btn-primary"></p>

</form>
Anne
  • 61
  • 5
  • You can not do this using CSS, not with that HTML structure. Whatever you want to manipulate based on the input field’s current state, would have to be a sibling following _after_ the input field. You can not select “backwards” or “a level up” with current CSS, see https://stackoverflow.com/questions/1014861/is-there-a-css-parent-selector – CBroe May 11 '20 at 11:15
  • @CBroe In this case, **you can** with `focus-within`. – Paulie_D May 11 '20 at 11:26
  • @Paulie_D well yeah, using that, you can make the label move when the input has focus, yes - but usually you’d not want it to move back, if the user actually entered something, and moves to the next field. Any combinations with `input:valid` or similar will not work with this structure. – CBroe May 11 '20 at 11:29
  • Thank you both! I've decided to go with a different solution based around both those notes. Rather than moving the label, I've added a placeholder, placed the label above the input at all times, then hidden the label (with opacity settings). I've used focus-within to make the label visible when you click the input. The main aim is to show what's in the field when you enter information, so this achieves that purpose too. – Anne May 11 '20 at 14:27

1 Answers1

0

You can use focus-within to manage this

form.wpcf7-form p label:focus-within span.formlabel

etc,

form.wpcf7-form p {
  position: relative;
  width: 100%;
  min-height: 1px;
  padding-top: 1.8rem;
  padding-right: 7.5px;
  padding-left: 7.5px;
  flex: 0 0 50%;
  max-width: 50%;
}

form.wpcf7-form p label {
  width: 100%;
  position: relative;
}

form.wpcf7-form p label span.formlabel {
  position: absolute;
  top: .8rem;
  z-index: 10;
  left: 1rem;
  white-space: nowrap;
  color: white;
  transition: all 1s ease;
}

form.wpcf7-form p label:focus-within span.formlabel {
  top: -1.8rem;
  color: red;
}

.form-control {
  display: block;
  width: 100%;
  padding: .8rem 0.75rem;
  font-size: 1rem;
  line-height: 1.5;
  color: #495057;
  background-color: #5D5D5D;
  background-clip: padding-box;
  border: none;
  border-radius: 0.25rem;
  transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}
<form method="post" class="wpcf7-form" novalidate="novalidate">

  <p>
    <label>
<span class="formlabel">Business Name</span>
<span class="wpcf7-form-control-wrap business-name">
<input type="text" name="business-name" value="" size="40" class="wpcf7-form-control wpcf7-text wpcf7-validates-as-required form-control" aria-required="true" aria-invalid="false">
</span> 
</label>
  </p>

</form>
Paulie_D
  • 95,305
  • 9
  • 106
  • 134