8

I need to be able to scroll up and after that down to find some element with Selenium.
I already saw many questions and answers, the main idea I found is self.web_driver.execute_script("return arguments[0].scrollIntoView(true);", element) and this is what I currently have in my code. But this is not good enough since this code is scrolling down only so this fails to find the element in case it is located in the upper part of the rollable view.
So I need a script that first scrolls up (page Up?) and after that begins scrolling down.
I tried something like this

self.web_driver.execute_script("return arguments[0].scrollIntoView(true);", element) 
self.web_driver.execute_script("window.scrollTo(0, -document.body.scrollHeight);")
self.web_driver.execute_script("return arguments[0].scrollIntoView(true);", element)

but this doesn't scroll up :(

Andersson
  • 51,635
  • 17
  • 77
  • 129
Prophet
  • 32,350
  • 22
  • 54
  • 79
  • An element is (just only one) element, why are you scrolling up and down again and again to get the element into view? The position of any element must be a fixed unless DOM changes. – undetected Selenium Feb 11 '18 at 12:36
  • Because this function (find_the_element) should be universal, sometimes the element is in the upper side and some times in the down side of the view and i can't know where it is. I need to pass the XPATH to the function and it will find (click on) the element – Prophet Feb 11 '18 at 12:43
  • Exactly, irrespective of the element being located up or down, will be brought into view. You simply have to pass the xpath. No need of scrolling up or down in particular. – undetected Selenium Feb 11 '18 at 12:46
  • But it doesn't work! self.web_driver.execute_script("return arguments[0].scrollIntoView(true);", element) scrolls down only! No matter if is it true or false inside the script – Prophet Feb 11 '18 at 12:58
  • `scrollIntoView` should scroll in any direction. Can you share the URL to a page where that's not the case? – Ian Lesperance Feb 11 '18 at 21:16
  • Also, why does the function need to be "universal"? Are you trying to write a helper function to use everywhere in your test suite? – Ian Lesperance Feb 11 '18 at 21:18
  • I can't share the page, but yes, this is a helper function. The automation here is based not on selenium directly but on selenium_helper – Prophet Feb 12 '18 at 09:30

7 Answers7

14

You can try below code to scroll page up:

from selenium.webdriver.common.keys import Keys

self.web_driver.find_element_by_tag_name('body').send_keys(Keys.HOME)

Another way (preferred) you can scroll up to required element:

element = self.web_driver.find_element_by_xpath('SOME_XPATH') # you can use ANY way to locate element
coordinates = element.location_once_scrolled_into_view # returns dict of X, Y coordinates
self.web_driver.execute_script('window.scrollTo({}, {});'.format(coordinates['x'], coordinates['y']))
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Andersson
  • 51,635
  • 17
  • 77
  • 129
  • Doesn't `location_once_scrolled_into_view` scrolls the element into the view by default and then return the co-ordinates? Why to invoke `execute_script('window.scrollTo())` again? – undetected Selenium Feb 11 '18 at 12:51
  • I'm not sure, but it seem that this property was changed, so in last versions it just returns the X, Y coordinates without scrolling to element – Andersson Feb 11 '18 at 13:08
  • If the definition is considered it says `Use this to discover where on the screen an element is so that we can click it. This method should cause the element to be scrolled into view.` and as the call to `click()` is involved without the _scrolling_ the method is not making any sense to me either. – undetected Selenium Feb 11 '18 at 14:55
  • @DebanjanB, this is initial description and scroll can be executed only in case `if self._w3c` returns `True`, but default value for WebElement object is `self._w3c = False`, so `else` block is executed by default - no scroll – Andersson Feb 11 '18 at 15:14
  • @Andersson after the first euphoria I see that your solution is not really works good. It since works better than the previous code but not really scrolls up... I need to debug to see what and why doesn't work good in my code. The problem is that this is not my code but a code of a person worked here before me and leaved me that strange code... – Prophet Feb 11 '18 at 17:48
3

I have discovered a handy tricky hacky stuff over the years (I've been using Selenium for 150 years).

Whenever you're unable to scroll up a form, just send keys into an input on the top of the page. The driver will find it and will automagically scroll up the page to perform the action.

Whenever I think about this trick, I realize being an old man isn't that bad.

Good luck you fresh sailor, see you on the shores of Selenia.

Zoette
  • 1,241
  • 2
  • 18
  • 49
3

Try this, it works good:

view_port_height = "var viewPortHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);"
element_top = "var elementTop = arguments[0].getBoundingClientRect().top;"
js_function = "window.scrollBy(0, elementTop-(viewPortHeight/2));"

scroll_into_middle = view_port_height + element_top + js_function

driver.execute_script(scroll_into_middle, element)
sashaboulouds
  • 1,566
  • 11
  • 16
3

This was very useful for me:

WebElement scrolling = new WebDriverWait(driver, 10)
            .until(ExpectedConditions.visibilityOfElementLocated(By.className("classSomething")));

//SCroll Down
((JavascriptExecutor) driver).executeScript("arguments[0].scrollTo(0, arguments[0].scrollHeight)", scrolling);

//Scroll Up
((JavascriptExecutor) driver).executeScript("arguments[0].scrollTo(0, arguments[0].scrollUp)", scrolling);
nosequeweaponer
  • 511
  • 10
  • 38
2

You can do it with also getBoundingClientRect() and scrollTo()

self.web_driver.execute_script("coordinates = arguments[0].getBoundingClientRect();scrollTo(coordinates.x,coordinates.y);", element)

I tested and it goes up and down.

Eduard Florinescu
  • 16,747
  • 28
  • 113
  • 179
  • FYI Python property `location_once_scrolled_into_view` do exactly the same as what JavaScript `getBoundingClientRect()` method do – Andersson Feb 11 '18 at 14:08
2

If you defined driver as webdriver.Chrome() or webdriver.Firefox(),you can use this code for scrolling up:

from selenium.webdriver.common.keys import Keys
driver.find_element_by_tag_name('body').send_keys(Keys.HOME)

Also, for scrolling down, you can try this code:

driver.execute_script("arguments[0].scrollTop = arguments[0].scrollHeight", scr1)

scr1 is your box xpath which you want to scroll it. You can scroll to middle of the page by this code, too:

driver.execute_script("arguments[0].scrollTop = arguments[0].scrollWidth", scr1)
Hamed Baziyad
  • 1,954
  • 5
  • 27
  • 40
0

For java I use next expression:

  WebElement element = drv.findElement(By.xpath("//div"));
  (drv as JavascriptExecutor).executeScript("arguments[0].scrollIntoView();", element);

The snippet scroll down to an element in Selenium until it is visible

Gleb Belyaev
  • 1,009
  • 1
  • 14
  • 23