void LayoutSliderContainer::layout()
{
    HTMLInputElement* input = toHTMLInputElement(node()->shadowHost());
    bool isVertical = hasVerticalAppearance(input);
    mutableStyleRef().setFlexDirection(isVertical ? FlowColumn : FlowRow);
    TextDirection oldTextDirection = style()->direction();
    if (isVertical) {
        // FIXME: Work around rounding issues in RTL vertical sliders. We want them to
        // render identically to LTR vertical sliders. We can remove this work around when
        // subpixel rendering is enabled on all ports.
        mutableStyleRef().setDirection(LTR);
    }

    Element* thumbElement = input->closedShadowRoot()->getElementById(ShadowElementNames::sliderThumb());
    Element* trackElement = input->closedShadowRoot()->getElementById(ShadowElementNames::sliderTrack());
    LayoutBox* thumb = thumbElement ? thumbElement->layoutBox() : 0;
    LayoutBox* track = trackElement ? trackElement->layoutBox() : 0;

    SubtreeLayoutScope layoutScope(*this);
    // Force a layout to reset the position of the thumb so the code below doesn't move the thumb to the wrong place.
    // FIXME: Make a custom Render class for the track and move the thumb positioning code there.
    if (track)
        layoutScope.setChildNeedsLayout(track);

    LayoutFlexibleBox::layout();

    mutableStyleRef().setDirection(oldTextDirection);
    // These should always exist, unless someone mutates the shadow DOM (e.g., in the inspector).
    if (!thumb || !track)
        return;

    double percentageOffset = sliderPosition(input).toDouble();
    LayoutUnit availableExtent = isVertical ? track->contentHeight() : track->contentWidth();
    availableExtent -= isVertical ? thumb->size().height() : thumb->size().width();
    LayoutUnit offset = percentageOffset * availableExtent;
    LayoutPoint thumbLocation = thumb->location();
    if (isVertical)
        thumbLocation.setY(thumbLocation.y() + track->contentHeight() - thumb->size().height() - offset);
    else if (style()->isLeftToRightDirection())
        thumbLocation.setX(thumbLocation.x() + offset);
    else
        thumbLocation.setX(thumbLocation.x() - offset);
    thumb->setLocation(thumbLocation);

    // We need one-off invalidation code here because painting of the timeline element does not go through style.
    // Instead it has a custom implementation in C++ code.
    // Therefore the style system cannot understand when it needs to be paint invalidated.
    setShouldDoFullPaintInvalidation();
}