You can use buffer, so instead of storing your markup in the $output
variable and then print that variable inside your wrapper, you can store everything in buffer, save it all in a variable and return that variable
function byn_recent_resources_shortcode($atts, $content = null) {
//...Put the same logic as in your question code
//...Change, for the code below, what you have, from $posts declaration to the end of the code
$posts = get_posts($args);
ob_start();
?>
<div class="resource-list" id="resource-list">
<div class="post-outer-wrap">
<?php
foreach($posts as $post) {
setup_postdata($post);
?>
<article>
<div class="thumbnail">
<?php if ( wp_attachment_is_image( $id ) ) { ?>
// Do option A
<?php } else { ?>
// Do option B
<?php } ?>
</div>
</article>
<?php } ?>
</div>
</div>
<?php
$output = ob_get_contents();
ob_end_clean();
wp_reset_postdata();
return $output;
}
add_shortcode('byn-recent-resources', 'byn_recent_resources_shortcode');
ob_start
will save the markup in a variable, including the product of the if statements, and then you just return that string.