WordPress function breaks widget’s markup?

wp_list_pages does not wrap it’s output in a ul or ol tag. That’s up to you.

In other words, if you just call wp_list_pages, it’s going to spit out a bunch of li tags, which your browser assumes is wrong and “corrects” the html as it sees fit. Try this:

function widget( $args, $instance ) {
    extract( $args );
    $title = apply_filters('widget_title', $instance['title'] );

    echo $before_widget;

    if ( $title )
        echo $before_title . $title . $after_title;

    echo '<ul>';
    wp_list_pages();
    echo '</ul>';

    echo $after_widget;
}