Radio button causes browser to jump to the top
Asked Answered
G

8

22

Problem:

When clicking on a label (for a radio button that has been intentionally hidden by positioning it off-screen), the browser undesirably jumps to the top of the page.

Note: This issue is inconsistent across different browsers -- It occurs in safari and chrome, and it does not occur in firefox or opera


Question:

How can I prevent the browser from jumping the scroll to the top of the page when clicking the radio button's label?


Example code:

JS Fiddle

• HTML

<div class="rdbut">
    <label class="colour">
        <input id="option-AVGANT1Y2PC" type="radio" name="Multi-licence" value="1 Year 2 PC|+23.99|0" checked="checked" />
        <span>£24.99</span></label>
</div>
<div class="rdbut">
    <label class="colour">
        <input id="option-AVGANT2Y2PC" type="radio" name="Multi-licence" value="2 Year 2 PC|+34.00|0" checked="checked" />
        <span>£35.00</span></label>
</div>

• CSS

.rdbut {
    margin: 0px;
}

.rdbut label {
    float: left;
    width: 65px;
    margin: 4px;
    background-color: #EFEFEF;
    box-shadow: 0px 1px 3px rgba(50, 50, 50, 0.25);
    border: none;
    overflow: auto;
    display: inline;
}

.rdbut label span {
    text-align: center;
    font-size: 12px;
    padding: 3px 8px;
    display: block;
}

.rdbut label input {
    position: absolute;
    top: -9999px;
    left: -9999px;
}

.rdbut input:checked+span {
    background-color: #404040;
    color: #F7F7F7;
}

.rdbut .colour {
    background-color: #FF8E22;
    color: #ffffff;
}
Graham answered 19/6, 2014 at 5:46 Comment(4)
CSS has no effect on the page position at clicking. Do you have any Javascript 'attached' to the radio buttons?Hoarsen
Hi, no none at all. From doing a search i cant seem to find any clear answers.Graham
Is or can you put it online?Hoarsen
I have an example on JSfiddle, scroll to the radio button in the result section. jsfiddle.net/rob_tb/XkQ7TGraham
H
28

Interesting. I don't know exactly why it behaves that way, but curing the unwanted behavior is easy: exchange the CSS top and left values of the radio inputs for visibility: hidden.

Like this:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Demo</title>
    <style>
    #content {
        width: 500px;
    }
    .rdbut {
        margin:0px;
    }
    .rdbut label {
        float:left;
        width:65px;
        margin:4px;
        background-color:#EFEFEF;
        border:none;
        overflow:auto;
        display:inline;
    }
    .rdbut label span {
        text-align:center;
        font-size: 12px;
        padding:3px 8px;
        display:block;
    }
    .rdbut label input {
        position:absolute;
        t/op: -9999px;
        l/eft: -9999px;
        visibility: hidden;
    }
    .rdbut input:checked + span {
        background-color:#404040;
        color:#F7F7F7;
    }
    .rdbut .colour {
        background-color:#FF8E22;
        color:#ffffff;
    }
    </style>
</head>
<body>
    <div id="content">
        <p>"Lorem ipsum" goes here.
        </p>
        <div class="rdbut">
            <label class="colour"><input id="option-AVGANT1Y2PC" type="radio" name="Multi-licence" value="1 Year 2 PC|+23.99|0" checked="checked" />
            <span>£24.99</span></label>
        </div>
        <div class="rdbut">
            <label class="colour"><input id="option-AVGANT2Y2PC" type="radio" name="Multi-licence" value="2 Year 2 PC|+34.00|0" checked="checked" />
            <span>£35.00</span></label>
        </div>
        <div class="rdbut">
            <label class="colour"><input id="option-AVGANT1Y2PC" type="radio" name="Multi-licence" value="1 Year 2 PC|+23.99|0" checked="checked" />
            <span>£24.99</span></label>
        </div>
    </div>
</body>
</html>

Updated JSFiddle here: http://jsfiddle.net/XkQ7T/1/.

.
By the way, setting checked on every radio button is no use - only the last one is actually checked. And it invalidates your code. Also, you need form tags around the group of radio inputs.

Hoarsen answered 20/6, 2014 at 9:17 Comment(5)
This worked great as I was using this: codepen.io/davidicus/pen/pvObpV but wanted my <label>s at the bottom instead of the at the top. visibility: hidden cured the annoying 'jump.' :)Crus
Don't do this. It breaks accessibility (keyboard and screen readers).Mediatorial
@Mediatorial - Not doing this means that normal and disabled users suffer from the radio jump problem, doing this means that only the disabled do?Hoarsen
Same problem I was facing today and you fix, work for me. Thanks :)Sawbuck
Thank you! I was using opacity: 0; to hide it as I needed it to still be able to be linked to as an anchor, but that was resulting in this jumping.Northnorthwest
H
16

I have the same problem, I use @Frank Conijn's solution,but if the radio set visibility: hidden; or display:none,the label(for="#id") not work in IE8, at last, I fix it like this:

.rdbut label input {
  position:absolute;
 left: -9999px;
 }

do not set top value

Hashim answered 20/1, 2016 at 5:39 Comment(3)
IE8? In 2016? The extended support for Windows XP ended on April 8, 2014. And so it did for IE8. You should warn IE8 users that they should use Chrome or Firefox, if they must continue using XP.Hoarsen
@FrankConijn IE havent seen its prime yet, IE is powerfull and a sleeping giant, people talk about no support, we talk about support, IE is what Chrome never could be, IE has been friendly to developers, IE has a great debugger that never lags, IE is utterly awesomeEllipticity
@iiiml0sto1 -- Everyone's entitled to their opinion. But I'm talking about IE8.Hoarsen
S
10

The accepted answer is not accessible: visibility: hidden; will hide your content from screen readers. Regardless, the trouble is here:

.rdbut label input {
    position: absolute;
    top: -9999px;
    left: -9999px;
}

Specifically, the top: -9999; is causing the browser to try and go up to that point.

I like to set a class for hiding stuff like this, with the following parameters. Then you can just stick it anywhere:

.visually-hidden {
  position: absolute;
  left: -9999px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

Note the top: auto; which should prevent the jump.

Straitjacket answered 23/3, 2018 at 15:6 Comment(0)
I
6

Here's what I did, and it worked well and still allowed for accessibility.

.hiddenInput {
  opacity: 0;
  height: 0;
  width: 0;
  margin: 0;
  padding: 0;
  position: fixed;
  top: 0;
}

That way the input is always in "view" so the label never has to forcibly scroll to it. The 'top: 0' is optional, for me it defaulted to the middle of my screen, I just put it somewhere explicitly.

Incorporate answered 19/2, 2019 at 16:21 Comment(3)
The other ones didn't work for me, but this one did. +1Fervid
Thank you so much for this answer! position: fixed instead of position: absolute fixed my issue. For those that want a good primer on why it is bad to use visibility: hidden look no further than this Medium article: blog.bitsrc.io/…Quay
This is really the best answer. All others break accessibility. There is no need to send the radio button off-screen.Peekaboo
G
2

Just add "display:none" to radio button.

input[type="radio"]{display:none;}
Gehlenite answered 21/6, 2021 at 5:25 Comment(0)
C
2

if you customize your radiobutton, don't hide it from page with display:none and don't use big left:-9999px.

Better use opacity:0, width:1px, height:1px and let the radio be close to your fake-radio button

<style>
.radio-button__container{
  position: relative
}
.radio-button{
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  bottom: 0; 
  left: 0;
}

</style>
Cabriole answered 21/2, 2022 at 16:13 Comment(0)
U
0

The reason why the browser jumps is that the input (radio or checkbox) and its labels are far away from each other, and when you click the visible label, the input gets the focus, so the browser goes where the input (focus) is.

Change the layout: put the input, the label and the ::before element of the label in a grid. The grid fixes the positions, so you can hide the input on the spot. This way the label and the input will not diverge, so focus will not make problem:

<style>
    div {
        display: grid;
        grid-template-columns: auto;
    }
    input {
        display: none;
        grid-column: 1 / 2;
    }
    label {
        grid-column: 1 / 2;
        display: grid;
        grid-template-columns: auto auto;
    }
    label::before {
        grid-column: 1 / 2;
        content: "";
        /* all necessary styling for the fancy input*/
    }
    </style>

    <html>
    <div>
       <input type="radio" id="a"><label for="a">Label text</label>
    </div>
    </html>
Ultramundane answered 6/5, 2021 at 8:53 Comment(0)
T
0

display: none; or visibility: hidden - > not gonna help you if you need an accessibly :( It's will fix an issue with page scroll but create an issue for the Screen readers.

This variant works good for me (thanks @James Hang!):

    input{
          opacity: 0;
          height: 0;
          width: 0;
          margin: 0;
          padding: 0;
          position: fixed;
          top: 0;
    }
Teasel answered 15/5, 2023 at 16:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.