ChatGPT解决这个技术问题 Extra ChatGPT

Scroll Element into View with Selenium

Is there any way in either Selenium 1.x or 2.x to scroll the browser window so that a particular element identified by an XPath is in view of the browser? There is a focus method in Selenium, but it does not seem to physically scroll the view in FireFox. Does anyone have any suggestions on how to do this?

The reason I need this is I'm testing the click of an element on the page. Unfortunately the event doesn't seem to work unless the element is visible. I don't have control of the code that fires when the element is clicked, so I can't debug or make modifications to it, so, easiest solution is to scroll the item into view.

You may try this hacky one if nothing else works for you: stackoverflow.com/a/53771434/7093031
3 ways to do it JavascriptExecutor js = (JavascriptExecutor) driver; js.executeScript("window.scrollBy(0,250)", "”); Actions action = new Actions(driver); action.moveToElement(element).perform(); WebElement element = driver.findElement(By.<locator>)); element.sendKeys(Keys.DOWN);

i
iliketocode

Have tried many things with respect to scroll, but the below code has provided better results.

This will scroll until the element is in view:

WebElement element = driver.findElement(By.id("id_of_element"));
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", element);
Thread.sleep(500); 

//do anything you want with the element

This is a neat solution for when you may have an element with position: fixed on your page and it is obscuring the element Selenium wants to click. Quite often these fixed elements go at the bottom, so setting scrollIntoView(true) moves it nicely to the top of the viewport.
Based on the newest version of selenium (2.53), this is now a great helper solution. Selenium is not always scrolling the element into view, so this definitely comes in handy.
Pass in true to scrollIntoView if the object you're scrolling to is beneath where you currently are, false if the object you're scrolling to is above where you currently are. I had a hard time figuring that out.
Why do you need thread sleep? executeScript should be synchronous
@riccardo.tasso a sleep might have been implemented to deal with the unknown of the target app. If it has dynamic scrolling, or a single-page app that loads the next bit of the page after scrolling, among other possibilities. Speaking from experience, Selenium has frequently broken my company's site because the automated action occurred faster than the Javascript could complete, and thus passed an incomplete data model. Some places may consider it a bug, but I was told "No human could ever invoke such a scenario, so it's not a real bug." C'est la vie.
s
supervacuo

You can use the org.openqa.selenium.interactions.Actions class to move to an element.

Java:

WebElement element = driver.findElement(By.id("my-id"));
Actions actions = new Actions(driver);
actions.moveToElement(element);
actions.perform();

Python:

from selenium.webdriver.common.action_chains import ActionChains
ActionChains(driver).move_to_element(driver.sl.find_element_by_id('my-id')).perform()

Will this work if the WebElement is not in the View Port?
@Dominik: How will Selenium move the mouse to an element that is outside the screen? OBVIOUSLY it must first scroll the element into view and then move the mouse to it. I tested it. This code works on Firefox Webdriver 2.48 but there is a bug: When you have an iframe in a page the scrolling does not work correctly in the iframe while element.LocationOnScreenOnceScrolledIntoView scrolls correctly. (Although the documentation says that this command only returns a location, it also scrolls!)
The docs at seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/… now clearly state "Moves the mouse to the middle of the element. The element is scrolled into view and its location is calculated using getBoundingClientRect."
The above code is "the official way" Java Selenium wants you to do scroll an element into viewport however after trying many things the JS implementation seemed to work more reliably to me. This method in particular.
Did not work for me :-| Used stackoverflow.com/a/23902068/661414 instead.
L
Liam
JavascriptExecutor js = (JavascriptExecutor) driver;
        js.executeScript("javascript:window.scrollBy(250,350)");

You may want to try this.


Thanks. I needed to use this method in a case where a Selenium's auto-scroll was causing another element to obscure the element I needed to click on. I was able to scroll an arbitrary amount to make the element visible in the viewport, without being obscured.
This will only work in FIrefox, Chrome and IE dont support this method
This is why you use js.ExecuteScript("arguments[0].scrollIntoView(true);" + "window.scrollBy(0,-100);", e); for IE and Firefox and js.ExecuteScript("arguments[0].scrollIntoViewIfNeeded(true);", e); for Chrome. Simple.
((JavascriptExecutor) driver).executeScript("javascript:window.scrollBy(0,250)"); This worked in Chrome. And the only solution that actually worked for me. Same situation as the first commenter, I had a fixed element at the bottom that kept obscuring the element I needed to click.
i
iliketocode

If you want to scroll on the Firefox window using the Selenium webdriver, one of the ways is to use JavaScript in the Java code. The JavaScript code to scroll down (to bottom of the web page) is as follows:

JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.scrollTo(0, Math.max(document.documentElement.scrollHeight, document.body.scrollHeight, document.documentElement.clientHeight));");

D
DevDave

Targeting any element and sending down keys (or up/left/right) seems to work also. I know this is a bit of a hack, but I'm not really into the idea of using JavaScript to solve the scrolling problem either.

For example:

WebElement.sendKeys(Keys.DOWN);

This is no less of a hack than using js and it really is the simplest thing. I found this primarily a problem with IE where a click tries to scroll the element into view but doesn't quite make it. Solution is just as elegant using {PGUP} if done with proper try/catch/loop scenario.
You saved my day! Thanks
In my case page down was the thing that worked. This is a nice hack (vs all js hacks).
Thanks @DevDave! Equivalent in C#: var elem = driver.FindElement(By.Id("element_id")); elem.SendKeys(Keys.PageDown);
i
iliketocode

In Selenium we need to take the help of a JavaScript executor to scroll to an element or scroll the page:

je.executeScript("arguments[0].scrollIntoView(true);", element);

In the above statement element is the exact element where we need to scroll. I tried the above code, and it worked for me.

I have a complete post and video on this:

http://learn-automation.com/how-to-scroll-into-view-in-selenium-webdriver/


@Mukesh otwani the above code will scroll down,but how abt scroll up without using any pixels defined in it.
P
Peter Mortensen
webElement = driver.findElement(By.xpath("bla-bla-bla"));
((JavascriptExecutor)driver).executeScript("arguments[0].scrollIntoView();", webElement);

For more examples, go here. All in Russian, but Java code is cross-cultural :)


Can I understand why there is a -1 for this solution?
Because it only works in Firefox. No other browsers support this method.
If someone needs a translation from Russian for the abovementioned document, will be happy to help.
M
Mohsin Awan

You can use this code snippet to scroll:

C#

var element = Driver.FindElement(By.Id("element-id"));
Actions actions = new Actions(Driver);
actions.MoveToElement(element).Perform();

There you have it


A
Ahmed Ashour

This worked for me:

IWebElement element = driver.FindElements(getApplicationObject(currentObjectName, currentObjectType, currentObjectUniqueId))[0];
 ((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].scrollIntoView(true);", element);

A
Ashley Frieze

I found that the bounding rect of my element was not correct, leading to the browser scrolling well off the screen. However, the following code works rather well for me:

private void scrollToElement(WebElement webElement) throws Exception {
    ((JavascriptExecutor)webDriver).executeScript("arguments[0].scrollIntoViewIfNeeded()", webElement);
    Thread.sleep(500);
}

This should be the official answer. It works flawlessly!
This is the only correct answer. In case the app has a fixed header and a footer, only this solution will work. Thank you.
P
Peter Mortensen

Use the driver to send keys like the pagedown or downarrow key to bring the element into view. I know it's too simple a solution and might not be applicable in all cases.


This is nonsense. You may have to send a dozen of page down on a large page. It is slow and not reliable.
Yes. I agree. But I did say "not applicable in all cases"
Finding some known element in the viewable page and sending PageDown element.SendKeys(Keys.PageDown); worked for me.
I'd advise to use Alt key so that you don't scroll the page and use try/except (Python) clause to handle errors which can occur while trying to send keys to some elements.
R
Robbie Wareham

From my experience, Selenium Webdriver doesn't auto scroll to an element on click when there are more than one scrollable section on the page (which is quite common).

I am using Ruby, and for my AUT, I had to monkey patch the click method as follows;

class Element

      #
      # Alias the original click method to use later on
      #
      alias_method :base_click, :click

      # Override the base click method to scroll into view if the element is not visible
      # and then retry click
      #
      def click
        begin
          base_click
        rescue Selenium::WebDriver::Error::ElementNotVisibleError
          location_once_scrolled_into_view
          base_click
        end
      end

The 'location_once_scrolled_into_view' method is an existing method on WebElement class.

I apreciate you may not be using Ruby but it should give you some ideas.


I declared the above in module Capybara :: module Node, and I needed to call native.location_once_scrolled_into_view instead of just location_once_scrolled_into_view . I also rescued ::Selenium::WebDriver::Error::UnknownError , which is what I'm getting often in Firefox 44.0.2. But I find this solution not to be flexible enough and ultimately put the <Element>.native.location_once_scrolled_into_view calls in the acceptance test itself, followed immediately by page.execute_script('window.scrollByPages(-1)') where needed.
Watir has the method Element#scroll_into_view which delegates to Selenium's location_once_scrolled_into_view. But both do nothing different from Seleniums default behavior so overflow elements still can obstruct whatever we try to click.
P
Peter Mortensen

The Ruby script for scrolling an element into view is as below.

$driver.execute_script("arguments[0].scrollIntoView(true);", element)
sleep(3)
element.click

A
Ahmed Ashour

Sometimes I also faced the problem of scrolling with Selenium. So I used javaScriptExecuter to achieve this.

For scrolling down:

WebDriver driver = new ChromeDriver();
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("window.scrollBy(0, 250)", "");

Or, also

js.executeScript("scroll(0, 250);");

For scrolling up:

js.executeScript("window.scrollBy(0,-250)", "");

Or,

js.executeScript("scroll(0, -250);");

L
Lukasz

This is a repeated solution with JavaScript, but with an added waiting for element.

Otherwise ElementNotVisibleException may appear if some action on the element is being done.

this.executeJavaScriptFunction("arguments[0].scrollIntoView(true);", elementToBeViewable);
WebDriverWait wait = new WebDriverWait(getDriver(), 5);
wait.until(ExpectedConditions.visibilityOf(elementToBeViewable));

?? <- what's mean?
A
AutomatedTester

Selenium 2 tries to scroll to the element and then click on it. This is because Selenium 2 will not interact with an element unless it thinks that it is visible.

Scrolling to the element happens implicitly so you just need to find the item and then work with it.


How is this an answer to the question?
doesn't appear to be working that way for me. Am getting 'element not clickable' errors for elements that are out of view
@DevDave I have the same problem, except in my case, selenium does not perform click action on the element and there is no exceptions. I didn't have the problem before and I don't know what has caused that.
The implicit scrolling varies between browsers. I have a test of an element in a pop-up menu partway down a page. With the Ruby gem selenium_webdriver 2.43 I find chromium-browser 37 (and I believe Internet Explorer) does indeed scroll the menu item into view and clicks it. But Firefox 32 doesn't seem to scroll at all, and then fails with "Element is not currently visible and so may not be interacted with".
This answer is wrong. According to the specification for Selenium 2.0 WebElement.click() requires the element to be visible in order to click on it. It will not scroll on your behalf.
c
cf stands with Monica

I have used this way for scrolling the element and click:

List<WebElement> image = state.getDriver().findElements(By.xpath("//*[contains(@src,'image/plus_btn.jpg')]"));

for (WebElement clickimg : image)
{
  ((JavascriptExecutor) state.getDriver()).executeScript("arguments[0].scrollIntoView(false);", clickimg);
  clickimg.click();
}

In my case, scrollIntoView(false) worked, but scrollIntoView(true) didn't. Either can work, it depends on your scenario.
My case is the opposite - true works, false fails, but only as far as the click goes. It does scroll correctly for false, and it's what I prefer, but for whatever reason Selenium still cannot see it for click. Using true scrolls everything way too high, but at least it works.
User sendkeys enter instead of click when ever possible - it avoids issues if browser is not at 100% zoom.
o
omnomnom
def scrollToElement(element: WebElement) = {
  val location = element.getLocation
  driver.asInstanceOf[JavascriptExecutor].executeScript(s"window.scrollTo(${location.getX},${location.getY});")
}

P
Peter Mortensen

Something that worked for me was to use the Browser.MoveMouseToElement method on an element at the bottom of the browser window. Miraculously it worked in Internet Explorer, Firefox, and Chrome.

I chose this over the JavaScript injection technique just because it felt less hacky.


Which programming language is this?
A
Ahmed Ashour

You may want to visit page Scroll Web elements and Web page- Selenium WebDriver using Javascript:

public static void main(String[] args) throws Exception {

    // TODO Auto-generated method stub
    FirefoxDriver ff = new FirefoxDriver();
    ff.get("http://toolsqa.com");
    Thread.sleep(5000);
    ff.executeScript("document.getElementById('text-8').scrollIntoView(true);");
}

@AbhishekBedi I remember that its supported in Chrome too. Any specific problem you might have faced?
D
David Clarke

If you think other answers were too hacky, this one is too, but there is no JavaScript injection involved.

When the button is off the screen, it breaks and scrolls to it, so retry it... ¯\_(ツ)_/¯

try
{
    element.Click();
}
catch {
    element.Click();
}

this. this is so bad i can't even... Don't waste try catch all in this way, you can build better code by ready any other answer
s
sp324

In most of the situation for scrolling this code will work.

WebElement element = driver.findElement(By.xpath("xpath_Of_Element"));                 
js.executeScript("arguments[0].click();",element);

f
frianH

JAVA

Try scroll to element utilize x y position, and use JavascriptExecutor with this is argument: "window.scrollBy(x, y)".

Following import:

import org.openqa.selenium.WebElement;
import org.openqa.selenium.JavascriptExecutor;

First you need get x y location the element.

//initialize element
WebElement element = driver.findElement(By.id("..."));

//get position
int x = element.getLocation().getX();
int y = element.getLocation().getY();

//scroll to x y 
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.scrollBy(" +x +", " +y +")");

k
kiranjith

I am not sure if the question is still relevant but after referring to scrollIntoView documentation from https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView.

The easiest solution would be

executor.executeScript("arguments[0].scrollIntoView({block: \"center\",inline: \"center\",behavior: \"smooth\"});",element);

This scrolls the element into center of the page.


M
Masih Jahangiri

Javascript

The solustion is simple:

const element = await driver.findElement(...)
await driver.executeScript("arguments[0].scrollIntoView(true);", element)
await driver.sleep(500);

d
djangofan

The default behavior of Selenium us to scroll so the element is barely in view at the top of the viewport. Also, not all browsers have the exact same behavior. This is very dis-satisfying. If you record videos of your browser tests, like I do, what you want is for the element to scroll into view and be vertically centered.

Here is my solution for Java:

public List<String> getBoundedRectangleOfElement(WebElement we)
{
    JavascriptExecutor je = (JavascriptExecutor) driver;
    List<String> bounds = (ArrayList<String>) je.executeScript(
            "var rect = arguments[0].getBoundingClientRect();" +
                    "return [ '' + parseInt(rect.left), '' + parseInt(rect.top), '' + parseInt(rect.width), '' + parseInt(rect.height) ]", we);
    System.out.println("top: " + bounds.get(1));
    return bounds;
}

And then, to scroll, you call it like this:

public void scrollToElementAndCenterVertically(WebElement we)
{
    List<String> bounds = getBoundedRectangleOfElement(we);
    Long totalInnerPageHeight = getViewPortHeight(driver);
    JavascriptExecutor je = (JavascriptExecutor) driver;
    je.executeScript("window.scrollTo(0, " + (Integer.parseInt(bounds.get(1)) - (totalInnerPageHeight/2)) + ");");
    je.executeScript("arguments[0].style.outline = \"thick solid #0000FF\";", we);
}

getViewPortHeight function is missing ... In an assumption you are taking the height of the target element
P
Peter Mortensen

I've been doing testing with ADF components and you have to have a separate command for scrolling if lazy loading is used. If the object is not loaded and you attempt to find it using Selenium, Selenium will throw an element-not-found exception.


P
Peter Mortensen

If nothing works, try this before clicking:

public void mouseHoverJScript(WebElement HoverElement) {

    String mouseOverScript = "if(document.createEvent){var evObj = document.createEvent('MouseEvents');evObj.initEvent('mouseover', true, false); arguments[0].dispatchEvent(evObj);} else if(document.createEventObject) { arguments[0].fireEvent('onmouseover');}";
    ((JavascriptExecutor) driver).executeScript(mouseOverScript, HoverElement);
}

P
Peter Mortensen

In Java we can scroll by using JavaScript, like in the following code:

driver.getEval("var elm = window.document.getElementById('scrollDiv'); if (elm.scrollHeight > elm.clientHeight){elm.scrollTop = elm.scrollHeight;}");

You can assign a desired value to the "elm.scrollTop" variable.


A
Ahmed Ashour

A solution is:

public void javascriptclick(String element)
{
    WebElement webElement = driver.findElement(By.xpath(element));
    JavascriptExecutor js = (JavascriptExecutor) driver;

    js.executeScript("arguments[0].click();", webElement);
    System.out.println("javascriptclick" + " " + element);
}