3

When changing the focus to another element of a website (e. g. to another input field by pressing TAB) which is not in your viewing area (e. g. you're at the bottom of the page and the new element is at the top) all browsers (tested Internet Explorer, Firefox, Chrome at Windows OS) seem to scroll just enough so that the element with the new focus is visible.

Example:

Image
Text
Input text
...
Footer

When you're at the Footer and Image to Input text is not inside your viewing area and you're now pressing tab so the focus jumps to Input text this field is now visible for you but not Image nor Text.

While this behaviour might be appropriate in most of the cases, in my case it isn't. To prevent it I suggest that focused elements are centered vertically. How can this be done?

To make it more clear:

This is the whole page:

enter image description here

I'm scrolling down to the bottom so only "This is the footer" is visible:

enter image description here

I'm now changing the focus by pressing tab. The focus jumps to the text input. Unfortunately the elements above this text field aren't visible:

enter image description here

mosquito87
  • 4,270
  • 11
  • 46
  • 77
  • Would a theoretical answer (without a fully functional javascript) be ok? – Asons Jan 08 '16 at 08:09
  • @LGSon I need at least someone pointing me to the right direction. I have know clue how to call this problem so I can't search for a solution. – mosquito87 Jan 08 '16 at 08:17
  • @Drako: I don't want to prevent the change completely but the new focussed element should be centered vertically (it's in the center of the screen so the elements above it are visible too). – mosquito87 Jan 08 '16 at 08:19
  • Ok, in my new comment try to change disabled for change the style: $(this).css('margin-left', '50%'), work? – Drako Jan 08 '16 at 08:23

1 Answers1

5

If one wrap both image and text with the input into a label, it appears to work without script.

<label for="input1">
  <img src="http://placehold.it/350x50"><br>
  Some text that should be visible
  <input id="input1" type="text">
</label>
<br>
<br>
<br>
<label for="input2">
  <img src="http://placehold.it/350x50"><br>
  Some text that should be visible
  <input id="input2" type="text">
</label>
<br>
<br>
<br>
<label for="input3">
  <img src="http://placehold.it/350x50"><br>
  Some text that should be visible
  <input id="input3" type="text">
</label>
<br>
<br>
<br>
<label for="input4">
  <img src="http://placehold.it/350x50"><br>
  Some text that should be visible
  <input id="input4" type="text">
</label>
<br>

I you can't use labels, I suggest you add an event handler, where you catch the "tab key", get the element with focus and either get its parent element (which likely contains your input and text and image) and scroll that parent into view

document.activeElement.parentNode.scrollIntoView();

or you need to calculate the document.activeElement's position and scroll it to the center, and here is a excellent way made by ThinkingStiff which I updated with a scrollIntoViewCenter method.

Element.prototype.documentOffsetTop = function () {
    return this.offsetTop + ( this.offsetParent ? this.offsetParent.documentOffsetTop() : 0 );
};
Element.prototype.scrollIntoViewCenter = function () {
  window.scrollTo( 0, this.documentOffsetTop() - (window.innerHeight / 2 ) );
};

And here is a snippet showing the scrollIntoViewCenter method.

Element.prototype.documentOffsetTop = function () {
  return this.offsetTop + ( this.offsetParent ? this.offsetParent.documentOffsetTop() : 0 );
};

Element.prototype.scrollIntoViewCenter = function () {
  window.scrollTo( 0, this.documentOffsetTop() - (window.innerHeight / 2 ) );
};


window.addEventListener("keyup", myScript);


function myScript(e) {
  if ('9' == e.keyCode) {  // tab = 9
    //find and vertically center focused input
    document.activeElement.scrollIntoViewCenter();
  }
}
<img src="http://placehold.it/350x50"><br>
Some text that should be visible
<input id="input1" type="text">
<br>
<br>
<br>

<img src="http://placehold.it/350x50"><br>
Some text that should be visible
<input id="input2" type="text">
<br>
<br>
<br>

<img src="http://placehold.it/350x50"><br>
Some text that should be visible
<input id="input3" type="text">
<br>
<br>
<br>

<img src="http://placehold.it/350x50"><br>
Some text that should be visible
<input id="input4" type="text">
<br>
<br>
<br>

<img src="http://placehold.it/350x50"><br>
Some text that should be visible
<input id="input5" type="text">
<br>
<br>
<br>

<img src="http://placehold.it/350x50"><br>
Some text that should be visible
<input id="input6" type="text">
<br>
<br>
<br>
Community
  • 1
  • 1
Asons
  • 84,923
  • 12
  • 110
  • 165
  • This goes to the right direction. Is that possible without JavaScript? – mosquito87 Jan 08 '16 at 08:29
  • Have you tried wrap all your image, text and input in a label which has its `for` attribute set to the input's id? ... That might do it. If you can (and don't get what I mean), post your html and I can make a snippet to show you. – Asons Jan 08 '16 at 08:37
  • @mosquito87 I updated my answer with something that appears to work without script. – Asons Jan 08 '16 at 08:48
  • HTML is created on server-side by a framework. So I'm not able to influence HTML directly. I'm testing your suggestions. Thanks. – mosquito87 Jan 08 '16 at 08:48
  • Seems the framework only provides the functionallity to create a label with a text or create HTML-elements with one label. But the label can't act as a container. I'm trying your JS. – mosquito87 Jan 08 '16 at 08:50
  • @mosquito87 Updated my answer again, with a custom `scrollIntoViewCenter` script snippet. – Asons Jan 08 '16 at 09:06
  • @mosquito87 Updated my answer one more time, rewrote it completely with a working snippet of both the non script version and the custom scrollIntoViewCenter script, so you can see it in action. – Asons Jan 08 '16 at 09:35