wp_nav_menu does not take arguments?

The items_wrap argument is in fact a sprintf-ed argument.

When you look into Core source:

'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>'

…you see that you have to use the arguments to let core do its work.

sprintf( $args->items_wrap, esc_attr( $wrap_id ), esc_attr( $wrap_class ), $items );

Here’re the %-arguments:

  • %1$s -> $wrap_id
  • %2$s -> $wrap_class
  • %3$s -> $items

Now to replace the container, you’ll need to use for e.g. something like the following:

'items_wrap' => '<div id="1%$s" class="%s$s">%3$s</div>'

Keep in mind that this is not the container. The container itself is only allowed to be a div or nav element. But you can extend the list of allowed container elements:

$allowed_tags = apply_filters( 'wp_nav_menu_container_allowedtags', array( 'div', 'nav' ) );