Format column length in SSMS output

You need to use CONVERT(VARCHAR(xx), ColumnName) on all columns if you want the column to appear shorter in text output view.

Convert your query into something like:

SELECT [Server] = CONVERT(VARCHAR(30), SERVERPROPERTY('Servername')) 
   , DatabaseName = CONVERT(VARCHAR(30), '''' + bs.database_name + '''')
   , LastDatabaseBackupDate = CONVERT(VARCHAR(30), MAX(bs.backup_finish_date))
FROM msdb.dbo.backupmediafamily  bmf
    INNER JOIN msdb.dbo.backupset bs ON bmf.media_set_id = bs.media_set_id  
WHERE  bs.[type] = 'D' 
GROUP BY bs.database_name  
ORDER BY bs.database_name;

This will give output similar to:

Server                         DatabaseName                   LastDatabaseBackupDate
------------------------------ ------------------------------ ------------------------------
[ServerName]                   'A'                            Sep 25 2015 11:32AM
[ServerName]                   'B'                            Apr 21 2015 12:09PM
[ServerName]                   'C'                            Feb 24 2015  9:16PM
[ServerName]                   'D'                            Oct  8 2014 11:02AM
[ServerName]                   'E'                            May 14 2014  6:27PM

(5 row(s) affected)

If you want to be able to dynamically change the column widths without modifying the T-SQL code, you'll need to use Dynamic SQL:

DECLARE @ColumnWidth VARCHAR(4);
DECLARE @Cmd NVARCHAR(MAX);

SET @ColumnWidth = '24';
SET @Cmd = '
SELECT [Server] = CONVERT(VARCHAR(' + @ColumnWidth + '), SERVERPROPERTY(''Servername'')) 
   , DatabaseName = CONVERT(VARCHAR(' + @ColumnWidth + '), '''''''' + bs.database_name + '''''''')
   , LastDatabaseBackupDate = CONVERT(VARCHAR(' + @ColumnWidth + '), MAX(bs.backup_finish_date))
FROM msdb.dbo.backupmediafamily  bmf
    INNER JOIN msdb.dbo.backupset bs ON bmf.media_set_id = bs.media_set_id  
WHERE  bs.[type] = ''D'' 
GROUP BY bs.database_name  
ORDER BY bs.database_name;
';

EXEC (@cmd);

Here, I've set the width to 24 for all columns, and it comes out looking like:

Server                   DatabaseName             LastDatabaseBackupDate
------------------------ ------------------------ ------------------------
SERVERNAME               'A'                      Sep 25 2015 11:32AM
SERVERNAME               'A'                      Apr 21 2015 12:09PM
SERVERNAME               'A'                      Feb 24 2015  9:16PM
SERVERNAME               'A'                      Oct  8 2014 11:02AM
SERVERNAME               'A'                      May 14 2014  6:27PM

(5 row(s) affected)

If you really want to go crazy and have the columns automatically size themselves, you would do this:

DECLARE @ColumnWidthServer VARCHAR(4);
DECLARE @ColumnWidthDatabase VARCHAR(4);
DECLARE @ColumnWidthLastBackup VARCHAR(4);

DECLARE @Cmd NVARCHAR(MAX);

SELECT @ColumnWidthServer = 1 + LEN(CONVERT(VARCHAR(128), SERVERPROPERTY('Servername')))
   , @ColumnWidthDatabase = 1 + MAX(LEN('''' + bs.database_name + ''''))
   , @ColumnWidthLastBackup = 1 + MAX(LEN(CONVERT(VARCHAR(128), bs.backup_finish_date)))
FROM msdb.dbo.backupmediafamily  bmf
    INNER JOIN msdb.dbo.backupset bs ON bmf.media_set_id = bs.media_set_id  
WHERE  bs.[type] = 'D';

SET @Cmd = '
SELECT [Server] = CONVERT(VARCHAR(' + @ColumnWidthServer + '), SERVERPROPERTY(''Servername'')) 
   , DatabaseName = CONVERT(VARCHAR(' + @ColumnWidthDatabase + '), '''''''' + bs.database_name + '''''''')
   , LastDatabaseBackupDate = CONVERT(VARCHAR(' + @ColumnWidthLastBackup + '), MAX(bs.backup_finish_date))
FROM msdb.dbo.backupmediafamily  bmf
    INNER JOIN msdb.dbo.backupset bs ON bmf.media_set_id = bs.media_set_id  
WHERE  bs.[type] = ''D'' 
GROUP BY bs.database_name  
ORDER BY bs.database_name;
';

EXEC (@cmd);

If you want something quick and easy, and can accept all column widths being the same, then try the -Y option of SQLCMD.exe:

C:\>SQLCMD -Y 3 -Q "SELECT name, name, name from sys.objects;"
nam nam nam
--- --- ---
sys sys sys
pla pla pla
spt spt spt
fai fai fai
MSr MSr MSr
sp_ sp_ sp_

 
OR, since the goal here is to email the output as a report, you can use sp_send_dbmail as follows:

DECLARE @ReportQuery NVARCHAR(MAX) = N'SET NOCOUNT ON;

PRINT ''<table style="border:1px solid black; width:100%;">
<tr><th>Server</th><th>DatabaseName</th><th>LastBackupDate</th></tr>'';

SELECT CONCAT(
       ''<tr><td>'',
       CONVERT(sysname, SERVERPROPERTY(''Servername'')),
       ''</td><td>'',
       N'''''''' + bset.[database_name] + N'''''''',
       ''</td><td>'',
       MAX(bset.backup_finish_date),
       ''</td></tr>'')
FROM   msdb.dbo.backupmediafamily bfam
INNER JOIN msdb.dbo.backupset bset
       ON bset.media_set_id = bfam.media_set_id
WHERE  bset.[type] = ''D''
GROUP BY      bset.[database_name]
ORDER BY      bset.[database_name];

PRINT ''</table>'';
';

EXEC msdb.dbo.sp_send_dbmail
  @profile_name = N'{your_Profile_name}',
  @recipients = N'{email_address(es)}',
--  @copy_recipients = N'copy_recipient [ ; ...n ]',
--  @blind_copy_recipients = N'blind_copy_recipient [ ; ...n ]',
  @subject = N'Reporty Stuffs', -- NVARCHAR(255)
  @body = N'Here is the report you asked for...',
  @body_format = 'html', -- HTML or TEXT (default)
--  @importance = 'importance', -- Low, Normal (default), or High
--  @sensitivity = 'sensitivity', -- Normal (default), Personal, Private, Confidential
  @query = @ReportQuery,
--  @execute_query_database = N'DB name',
  @query_result_header = 0; -- 0 or 1 (default)

Notes:

  1. In the Report Query (@ReportQuery in the example):
    1. SET NOCOUNT ON; is required, else "X row(s) affected" prints between the final </td></tr> and the </table> tag, messing up the rendering of the table
    2. CONCAT makes it easy to construct the HTML table row because you can skip doing CONVERT(NVARCHAR(x), ... for non-string columns of types that can implicitly convert. For pre-SQL Server 2012 (when CONCAT was introduced), just do the CONVERTs and normal string concatenation with +.
  2. Query output will come after the content of the @body variable (if there is any).
  3. @body_format = 'html' is required, else the < and > of the HTML tags will get translated into &lt; and &gt;, respectively, and you will see the HTML tags (since they won't actually be HTML tags).
  4. @query_result_header = 0 is required, else a column header line prints between the <table> tag and the initial <tr><td>, messing up the table rendering.