114

I am still learning and in response to one of my questions: here, I was told to that it might be due because the element in question is not in view.

I looked through the documentation and SO, here was the most relevant answer: here

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

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

When I try to use the above to scroll to the element: It says WebElement not defined.

I think this is because I have not imported the relevant module. Can someone point out what I am supposed to import?

Edit: As pointed out by alecxe, this was java code.

But in the meantime right after trying to figure it out for some time. I have found out the import method for WebElement:

from selenium.webdriver.remote.webelement import WebElement

Might help someone like me.

The how of it is also a good lesson, IMO:

Went to: Documentation The

class selenium.webdriver.remote.webelement.WebElement(parent, id_, w3c=False)

Need to be separated into the command form mentioned above.

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
Sid
  • 3,749
  • 7
  • 29
  • 62

7 Answers7

205

You are trying to run Java code with Python. In Python/Selenium, the org.openqa.selenium.interactions.Actions are reflected in ActionChains class:

from selenium.webdriver.common.action_chains import ActionChains

element = driver.find_element_by_id("my-id")

actions = ActionChains(driver)
actions.move_to_element(element).perform()

Or, you can also "scroll into view" via scrollIntoView():

driver.execute_script("arguments[0].scrollIntoView();", element)

If you are interested in the differences:

Community
  • 1
  • 1
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
  • 1
    Ah...there I was for 3 hours trying every method I found on SO and the documentation. I tried the first solution but must have messed it up somehow. I will read the ScrollIntoView Vs moveToElement. Just a quick question, I need the same steps to be done 100 times, I am thinking of using a `for` loop. Would this be a good approach? – Sid Jan 19 '17 at 14:46
  • @Sid difficult to say. In certain cases, you can just chain the actions in a loop and then perform once after the loop, but it all depends on a use case. See if it will makes sense to create a separate SO topic for that if help will be needed. Thanks. – alecxe Jan 19 '17 at 14:48
  • will `move_to_element(ele).perform()` simply scroll to an element, even if the element isn't currently in view? – oldboy Jun 27 '18 at 03:38
  • 1
    @alecxe I don't get how this works (it doesn't with my project) because how can selenium find the object to scroll to if the object isn't visible? Mine is unable to locate the element that I want it to scroll to. – jeepers mcface Feb 13 '19 at 22:05
  • 2
    When I called move_to as you suggested, I got selenium.common.exceptions.MoveTargetOutOfBoundsException: Message: (164, 1297) is out of bounds of viewport width (1366) and height (694). I'm grateful for your answer and I think this IS the way (and also I've learned about ActionChains from your answer), but looks like it needs a bit of improvement. Thanks1 – dotz Mar 23 '19 at 22:31
75

It's not a direct answer on question (its not about Actions), but it also allow you to scroll easily to required element:

element = driver.find_element_by_id('some_id')
element.location_once_scrolled_into_view

This actually intend to return you coordinates (x, y) of element on page, but also scroll down right to target element

Andersson
  • 51,635
  • 17
  • 77
  • 129
  • Thanks @Andersson I was trying to find the way to do this since you pointed out this might be the problem on the other question. :) – Sid Jan 19 '17 at 14:52
  • 2
    at first i appended `()` behind, and error ''dict' object is not callable', i checked the element type is `WebElement`. then i removed `()` and worked. isn't this a method? I mean, why no `()` need? – Lei Yang Jul 28 '17 at 02:17
  • 1
    @LeiYang, because location_once_scrolled_into_view is a Python [property](https://stackoverflow.com/questions/17330160/how-does-the-property-decorator-work). Properties takes no arguments (except object instance -self) and should be called without parenthesis – Andersson Jul 28 '17 at 04:30
  • 1
    @Andersson .move_to_element() didn't work for me (I commented on alecxe answer) but yours solution did. THANKS! – dotz Mar 23 '19 at 22:33
  • @LeiYang Here is the source code about `location_once_scrolled_into_view`, to help explain why `()` not need : [selenium/webelement.py at d3b6ad006bd7dbee59f8539d81cee4f06bd81d64 · SeleniumHQ/selenium](https://github.com/SeleniumHQ/selenium/blob/d3b6ad006bd7dbee59f8539d81cee4f06bd81d64/py/selenium/webdriver/remote/webelement.py) – DataAlchemist May 03 '20 at 07:55
  • It doesn't scroll to the element, if element is not visible, it doesn't scroll to that element and it returns {'x' : 0, 'y': 0} – ugola Apr 22 '22 at 05:34
14

In addition to move_to_element() and scrollIntoView() I wanted to pose the following code which attempts to center the element in the view:

desired_y = (element.size['height'] / 2) + element.location['y']
window_h = driver.execute_script('return window.innerHeight')
window_y = driver.execute_script('return window.pageYOffset')
current_y = (window_h / 2) + window_y
scroll_y_by = desired_y - current_y

driver.execute_script("window.scrollBy(0, arguments[0]);", scroll_y_by)
Neil C. Obremski
  • 18,696
  • 24
  • 83
  • 112
  • 1
    Thanks for your solution, tried other ways but element wasnt clickable. Some time not enought scroll, element was under "Chat box" on bottom, other code too much scroll element was on top below. menu – Wonka Feb 19 '20 at 16:22
8

Example:

driver.execute_script("arguments[0].scrollIntoView();", driver.find_element_by_css_selector(.your_css_selector))

This one always works for me for any type of selectors. There is also the Actions class, but for this case, it is not so reliable.

vitaliis
  • 4,082
  • 5
  • 18
  • 40
2

This can be done using driver.execute_script():-

driver.execute_script("document.getElementById('myelementid').scrollIntoView();")
ePandit
  • 2,905
  • 2
  • 24
  • 15
0

There is another option to scroll page to required element if element has "id" attribute

If you want to navigate to page and scroll down to element with @id, it can be done automatically by adding #element_id to URL...

Example

Let's say we need to navigate to Selenium Waits documentation and scroll page down to "Implicit Wait" section. We can do

driver.get('https://selenium-python.readthedocs.io/waits.html')

and add code for scrolling...OR use

driver.get('https://selenium-python.readthedocs.io/waits.html#implicit-waits')

to navigate to page AND scroll page automatically to element with id="implicit-waits" (<div class="section" id="implicit-waits">...</div>)

Andersson
  • 51,635
  • 17
  • 77
  • 129
0

You can scroll to the element by using javascript through the execute_javascript method. For example here is how I do it using SeleniumLibrary on Robot Framework:

web_element = self.selib.find_element(locator)
self.selib.execute_javascript(
    "ARGUMENTS",
    web_element,
    "JAVASCRIPT",
    'arguments[0].scrollIntoView({behavior: "instant", block: "start", inline: "start"});'
)
Antony Fuentes
  • 1,013
  • 9
  • 13