Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

ApeWare's avatar

Why is blade trimming left spaces and how to avoid??

I am working on an email template for our site and have a component that renders the text version of the email content. This particular component is supposed to generate centered: title, body, and call to action, so in the text version, I am trying to use the str_pad() function to center the text based on a 60 column layout.

It seems that Blade is trimming leading whitespace so my text always lines up left aligned.

Here is an example of how I set up the code:

...
@isset($title)
{{ str_pad(strtoupper($title), 60, ' ', STR_PAD_BOTH) }}
@endisset
...

It renders like this:

TEXT BLOCK CENTER                      

but I am expecting this:

                     TEXT BLOCK CENTER                      

if I do a dd():

{{dd(str_pad(strtoupper($title), 60, ' ', STR_PAD_BOTH))}}

it renders correctly in the dd().

Is there something I am missing which will allow the leading white spaces?

0 likes
44 replies
Cronix's avatar

That's purely an html display issue. HTML will only output a single consecutive space, unless   is used.

Try it with regular html to confirm. Just make a div tag with a bunch of spaces and a word. It will only display a single space and the word.

Snapey's avatar

How are you checking the output?

ApeWare's avatar

I am looking at Chrome dev tools. I have the output displaying in a <pre> tag and it shows the left spaces trimmed; I confirmed the prefix spacing is missing in chrome dev tools, but it shows the prefix spacing if I dd().

Snapey's avatar

as @cronix says, you cannot review the output in a browser since all white space is compressed to a single space

jlrdw's avatar

You could put your text in a div or span element and use a margin, or even padding.

ApeWare's avatar

@snapey, the trailing spaces are not compressed, just the leading spaces. If you have spaces in a <pre> tag, they will render properly and not be compressed or trimmed. I could manually create text with multiple spaces and they will render, just not in blade. Actually, if I do something like:

...
@isset($title)
    {{ str_pad(strtoupper($title), 60, ' ', STR_PAD_BOTH) }}
@endisset
...

it will render the 4 spaces before the {{ like this:

    TEXT BLOCK CENTER

So it is not the browser or pre tag stripping the leading whitespace.

@jlrdw, the intent is to use the text in a text version of email. I already have the html version that uses div span and table as needed; this is to add a text version to reduce spam score or to display content if people have HTML email turned off.

Snapey's avatar

it could be an issue that you are using blade tags specifically aimed at outputting safe html. Try using raw tag {!! ... !!} or just plain old echo

jlrdw's avatar

Or don't use blade for this.

ApeWare's avatar

@Snapey Thanks for the suggestion. I tried that but it returned the same results - left spaces are trimmed.

I also tried to dump into PHP, but that yielded same results - left spaces are trimmed:

@isset($title)
    @php
        echo str_pad(strtoupper($title), 60, ' ', STR_PAD_BOTH);
    @endphp
@endisset

@jlrdw Why wouldn't I use blade for this? Is there a specific reason Blade is trimming left space? I couldn't find anything in the docs about it.

jlrdw's avatar

In one of my forms I have a textarea that I want to have padding at top, so the text is to the right of an image

<p>Comments</p><br>
        <textarea class="rightdiv" name='comments'></textarea>

And here is the css

<style type="text/css">
    body {
                font-family: "Times New Roman", Times, serif;
                font-size: 16px;
                font:bold;
                color:#00F;
            }
    .rightdiv { width:495px; height: 250px;
                font-family: "Times New Roman", Times, serif;
                font-size: 1.1em;
                font:bold;
                color:#00F;
                margin-left:auto;
                margin-right:auto;
                text-align:left;
                padding-left:4px;
                padding-top:60px;    /*HERE*/
    }
</style>

It still seems you could use padding somehow.

ApeWare's avatar

You can't use CSS on a text email. I have all of the styling on the HTML version. The text version is intended to somewhat replicate the HTML version using plain text.

This particular component is to display centered: Title, sub-heading, content, button, and link. It should render something like this:

                  TEXT BLOCK CENTER                      
              Optional sub-heading text

    lLorem ipsum dolor sit amet, consectetuer 
   adipiscing elit. Fusce odio quam, cursus vel, 
             facilisis sed, velit.

    Morbi egestas justo ut ligula. Integer arcu. 
 Aenean lobortis volutpat massa. Nulla ultricies 
   aliquet dolor. Quisque vulputate nulla eget 
 dolor. Fusce nec diam ultricies massa convallis 
 egestas. Ut facilisis. Vestibulum vel ante eu felis 
  commodo tincidunt. Duis euismod elementum 
                    ipsum.

          [Button Label](http://google.com)

           [Link Text](http://github.com)

------------------------------------------------------------

note: spacing is not exact in post but you get the idea. Everything should calculate spacing to be centered based on a 60 column line.

I have other components that render left aligned, which obviously work fine, but I'm not sure why Blade is trimming left spaces.

jlrdw's avatar

Use the ascii code for space. I forget what the usage in PHP is, but I have used it in Visual Basic code.

EDIT:

echo chr(32); // as many times as needed
ApeWare's avatar

Thanks @jlrdw. Gave that a shot and it yields the same as using a space.

Here is a screenshot of how it renders. You can see the trailing spaces are there but the leading ones are trimmed.

It seems like it simply doesn't like leading spaces. If I use . it works fine.

@isset($title)
    {{ str_pad(strtoupper($title), 60, '.', STR_PAD_BOTH) }}
@endisset

I'll have to delve into the Laravel source to see what is happening. Not sure if this is intended or a bug.

Snapey's avatar

try pad with a printable character (e.g. '.') just to make sure it's not something daft elsewhere

jlrdw's avatar

@Snapey quit using words I have to look up daft haha You are expanding my vocabulary.

Snapey's avatar

@jlrdw in this case something that makes you say doh! afterwards... not that i am insinuating that @apeware will be in that situation

jlrdw's avatar

Ok this works

echo nl2br(str_repeat(' ', 30) . "hello world\r\nthis is a new line");

gives

                              hello world
this is a new line

Just a quick test.

First I ran across it that way had to study it, and the word daft.

ApeWare's avatar

@Snapey, that is what I was trying to show with my previous post. If I use a . character it works - adds the appropriate numbr of leading . to text.

@jlrdw, are you suggesting that I would have to write a function to calculate the number of leading spaces necessary to center the text and pass it into a str_repeat() function? It seems heavy handed when there is already the native str_pad() function.

I guess what I am trying to figure out is if there is something within the Blade code that automatically left trims strings and if there is a method to turn it off.

I think I will try to just send the text to the mailable and see how it renders in the email. From what I can tell, the chrome dev tools clearly shows it is being trimmed both in source and display; maybe if I send the view to a mailable it will render differently. It just really doesn't make sense why Blade would be set to ltrim() by default...or at least without a means to turn off this behavior.

ApeWare's avatar

@jlrdw I am familiar with str_repeat() but the advantage of str_pad() is you can give it a max width and it can automatically calculate the left and right padding to effectively center the text. If I were to use str_repeat() I would have to calculate the multiplier manually.

I appreciate your time and input in helping me find a solution. This is kinda frustrating because this doesn't seem like it should be difficult. :-)

spekkionu's avatar

Looking through the code for blade as well as the escaping functions and I don't see anything that would be trimming?

Can you take a look through your storage/framework/views folder for the compiled view in question? That will contain the actually php code that is being run after blade compiles the template. Maybe there is something there that will give a hint as to what is happening.

jlrdw's avatar

Yeah I tried with a dash, and it worked, I am thinking it just doesn't work with space. I even tried

echo nl2br(str_pad(strtoupper($title), 60, chr(32), STR_PAD_BOTH));

no luck but

echo nl2br(str_pad(strtoupper($title), 60, "-", STR_PAD_BOTH));

works like a champ, maybe you could use periods or something.

ApeWare's avatar

@spekkionu here is what it looks like in storage/frameworks/views - I have never bothered to look at these before. It looks like it is picking it up correctly though:


<?php if(isset($title)): ?>
    <?php echo e(str_pad(strtoupper($title), 60, '.', STR_PAD_BOTH)); ?>

<?php endif; ?>

<?php if(isset($subheading)): ?>
<?php echo e($subheading); ?>

<?php endif; ?>

<?php if(isset($text)): ?>
<?php echo e(wordwrap(trim(preg_replace("/[[:blank:]]+/", ' ', $text)), 60, "\n")); ?>

<?php endif; ?>

<?php if(isset($button)): ?>
[<?php echo e(isset($button) ? $button : ''); ?>](<?php echo e(isset($buttonHref) ? $buttonHref : '#'); ?>)
<?php endif; ?>

<?php if(isset($link)): ?>
[<?php echo e(isset($link) ? $link : ''); ?>](<?php echo e(isset($linknHref) ? $linknHref : '#'); ?>)
<?php endif; ?>

<?php if(isset($border) and $border == true): ?>
<?php $__env->startComponent('mail.components.divider.text'); ?>
<?php echo $__env->renderComponent(); ?>
<?php endif; ?>
ApeWare's avatar

@jlrdw re: stack overflow. It may come to that, but what I don't understand is the dd() does show the prepended spaces so not sure why once the Blade engine gets ahold of it, it seems to strip them out.

jlrdw's avatar

No not just blade, I have been playing in normal php, has to to with the optional arguments, but can't skip one and use last, have to skip both, then str_pad just defaults to pad on right side. Blade isn't issue.

If you figure this out, please post your solution, will help others, thanks, good luck.

spekkionu's avatar

If the compiled view file doesn't have anything that trims the value then it has nothing to do with blade as blade is done at that point.

Does it happen if you just render the view or is it only happening when you use it as an email template?

jlrdw's avatar

Ok, solved. It won't work in an html (browser). If you view the source, or use that same function to write to a text file on disk it works. But you said this isn't for an html page.

Where are you placing this plain text? If blade is involved sounds like a browser is involved. Otherwise write to a text file and display (retrieve) from that, but if you put it in a browser you are back to square one.

One interesting issue for sure.

ApeWare's avatar

@spekkionu I have not gotten to the point where I am mailing this yet, I am still working on the template components so I am rendering a test view, with test data, to work out the view logic. I am outputting this into a pre tag so the spaces should render fine and not be stripped off like they would be outside a <pre> tag. I am thinking I may have to just assume it will render properly in an email and move on to sending a test email to verify. The dd() is displaying the text properly, but Chrome tools and the <pre> are not, which is confusing.

I will try to whip up an email on Wednesday and see if it works there; if nothing else, I will have more information and will report back...unless someone has any insights in the meantime.

Thanks again all for taking the time to contribute. I really appreciate it. :-)

ApeWare's avatar

@jlrdw I am viewing source and it still strips off the leading spaces. I am still going to send it through an email and see if it changes anything but since it isn't displaying in the source, I am concerned.

I will follow-up once I get the mailable setup.

Next

Please or to participate in this conversation.