Tres Leches Cake
1
9x13 cake
Dessert
Course
Print Recipe
Ingredients
Directions
Cake
Unsalted butter, softened, for the pan
Jump
1 c
unbleached all-purpose flour
Jump
1 ½ tsp
baking powder
Jump
½ tsp
kosher salt
Jump
5 lg
eggs, at room temperature
Jump
1 c
granulated sugar
Jump
c
whole milk
Jump
½ tsp
pure vanilla extract
Jump
Soaking Liquid
1
14 oz can sweetened condensed milk
Jump
1
12 oz can evaporated milk
Jump
c
heavy cream
Jump
½ c
rum or tequila (optional)
Jump
Pinch kosher salt
Jump
Whipped Cream Topping
2 ½ c
heavy cream
Jump
2 tbsp
confectioners’ sugar
Jump
tsp
pure vanilla extract
Jump
½ tsp
salt
Jump
2-3 c
sliced or diced fruit, such as mango, strawberries, raspberries or peaches (optional
Jump

Tres leches (or “three milks”) cake uses a combination of condensed milk, evaporated milk, and regular cow’s milk to create a spongy, custardy cake that’s soaked through with a sweet, milky sauce. The combination of milks creates a rich, layered flavor that’s mild enough to use as a blank slate for adding caramel, coffee, toasted coconut, lime zest, cinnamon, and much more.

Directions

  1. Position a rack in the center of the oven and heat the oven to 350°F.
  2. Butter the bottom and sides of a 9-by-13-inch Pyrex baking dish or a nonreactive metal pan. Line the bottom of the baking dish or pan with parchment paper and lightly butter the parchment.
  3. Mix the flour, baking powder, and salt into a medium bowl with a whisk and sift together. Set aside.
  4. Separate the eggs, putting the whites and yolks in separate clean, dry bowls. With an electric mixer, beat the yolks with half of the sugar on medium speed until the mixture is pale and ribbon-like, about 3 minutes. Add the milk and vanilla and beat until combined, 1 minute more.
  5. Clean and dry the beaters and then beat the egg whites, gradually increasing the speed to high, until they reach soft peaks, 2 to 3 minutes. Add the remaining ½ cup sugar little by little, continuing to beat on high, until you reach firm but not dry peaks, about 1 to 2 minutes more.
  6. Whisk about a third of the dry ingredients into the yolk mixture until thoroughly combined. Gently fold in a third of the egg whites with a spatula. Fold in the remaining dry ingredients and egg whites, alternating, in two more batches each, until fully incorporated, making sure not to overmix and deflate the eggs.
  7. Pour the batter into the prepared dish or pan and bake in the center of the oven until a toothpick inserted in the center comes out clean, 20 to 25 minutes. Let the cake cool in the pan on a rack for 10 minutes, then invert the cake onto the rack, remove the parchment, and let cool completely.
  8. Return the cake to the baking dish or pan and cool. Meanwhile, prepare the soaking liquid.
  9. In a small-medium saucepan over medium heat, stir together the evaporated milk, heavy cream, and salt. Cook, stirring once in a while to avoid scorching, until it begins to bubble around the edges, 3 to 5 minutes. Remove from the heat, whisk in condensed milk until it is well blended and add the liquor if using. Pour into a heatproof 4-cup measuring cup.
  10. With a toothpick, prick the cake to the bottom in 1/2-inch intervals. Pour the soaking liquid slowly over the cake, starting at the edges and pausing to let it soak in before adding more. Cover loosely with plastic wrap and refrigerate until the cake is well chilled, at least 2 hours and up to 24 hours.
  11. To make the whipped cream topping, beat the heavy cream with an electric mixer on medium speed with the whisk attachment on medium speed. When it begins to thicken, slowly add the sugar and vanilla and continue to beat just until it holds firm peaks, 3 to 4 minutes (be careful not to overbeat). Spread the whipped cream all over the top of the cake, top with fruit if desired and serve.

Fany Gerson

Fany Gerson has been featured in the New York Times, Gourmet, Fine Cooking, Saveur Magazine, Fine Cooking, Food and Wine and New York magazines, among others. She launched the acclaimed La Newyorkina, an artisanal Mexican frozen treats and sweets business in 2010. She is also the Chef and co-owner of Dough, an artisan gourmet doughnut shop in New York. A graduate of the Culinary Institute of America, Fany has worked in a range of fine-dining kitchens around the world including 3 Michelin starred Akelare in Spain and Eleven Madison Park in New York. She has written two books, My Sweet Mexico which was nominated for a James beard award 2010 for Best baking and pastry cookbook and Paletas. Fany also opened her first brick and mortar for La Newyorkina on October 2016 in the West Village of New York City.

[email_signup id="3"]
<div class="email-subscribe exp-subscribe subscribe"> <div class="alert alert-success exp-success ga-etembed-success" style="display:none;"> Great! You've signed up successfully! </div> <div class="alert alert-danger exp-error" style="display:none;"> We are experiencing an error, please try again. </div> <form name="subscribe" id="email-signup" class="email-signup-form" action="https://www.tastecooking.com/wp-admin/admin-ajax.php" method="POST" target="_top" data-event-assigned="false"> <fieldset class="form-group form-inline email-submit-group"> <label for="email-address" class="sr-only">Email Address</label> <input id="email-newsletter" type="email" placeholder="your@email.com" class="email-newsletter text email form-control" name="email" value=""> <button type="submit" value="Subscribe" name="subscribe" class="btn btn-primary email-submit-btn ga-etembed-success"> <i class="fa fa-envelope"></i> Subscribe </button> </fieldset> <small class="exp-small terms" style=""> By clicking Subscribe, I acknowledge that I have read and agree to the Penguin Random House <a href="http://www.penguinrandomhouse.com/privacy/" target="_blank">Privacy Policy</a> and <a href="http://www.penguinrandomhouse.com/terms/" target="_blank">Terms of Use</a> and agree to receive news and updates from TASTE and Penguin Random House. </small> <fieldset class="field-group checkboxes" style="display:none"> <div class="checkbox"> <label> <input type="checkbox" name="programs[]" value="505,50501,1" class="exp-checkbox" checked="checked"> <span><strong>Tastebook General</strong></span> </label> </div> <div class="checkbox"> <label> <input type="checkbox" name="programs[]" value="505,50502,1" class="exp-checkbox" checked="checked"> <span><strong>Tastebook Promo</strong></span> </label> </div> </fieldset><!-- /.checkboxes --> <input type="hidden" name="data_acq_code" value="TASTE_POPUP_STATIC_ONGOING" /> <input type="hidden" name="data_programs" value="50501|505,50502|505" /> <input type="hidden" name="form_id" value="3" /> <input type="hidden" name="partner" value="" /> <input type="hidden" name="action" value="crown_email_signup_submit" /> <input type="hidden" name="ref_url" value="" /> </form> </div> <script> jQuery(document).ready(function () { var unassigned_forms; setInterval( function() { //Check for unassigned forms var forms = jQuery( '.email-signup-form' ); unassigned_forms = false; forms.each( function( index ) { if ( jQuery( this ).attr( 'data-event-assigned' ) === 'false' ) { unassigned_forms = true; } }); if ( unassigned_forms ) { forms.off( 'submit' ).on( 'submit', function ( e ) { forms.attr( 'data-event-assigned', 'true' ); e.preventDefault(); // Basic email validation var email = jQuery(e.target).find('.email-newsletter').val(), valid_email = false, groupEl = jQuery(e.target).closest('.email-subscribe'); if ( !!email && typeof(email) === "string" ) { var email_array = email.split('@'); if ( email_array.length === 2 ) { if ( email_array[1].split('.').length > 1 ) { valid_email = true; } } } if ( valid_email ) { jQuery('.alert-danger').hide(); // Show loading gif groupEl.find('.email-signup-form').hide(); groupEl.find('.email-submit-loading').show(); // Populate ref_url jQuery(this).find('input[name="ref_url"]').val(window.location.href); // Generate Payload var payload = jQuery(this).serializeArray(); jQuery.ajax({ url: jQuery(this).attr('action'), type: 'POST', data: payload, success: function (data) { // Hide loading spinner groupEl.find('.email-signup-form').show(); groupEl.find('.email-submit-loading').hide(); // Display success msg var target = jQuery(e.target); jQuery(e.target).hide(); jQuery(e.target).parent().find('.alert-success').show(); jQuery(e.target).parent().find('#downloadbtn').show(); }, fail: function (err) { // Hide loading spinner groupEl.find('.email-signup-form').show(); groupEl.find('.email-submit-loading').hide(); // Display failure msg var target = jQuery(e.target); jQuery(e.target).hide(); jQuery(e.target).parent().find('.alert-danger').show(); } }); } else { groupEl.find('.alert-danger').html('Please enter a valid email address.').show(); } }); forms.off( 'keypress' ).on( 'keypress', function ( e ) { if ( e.which === 13 ) { e.preventDefault(); jQuery( this ).submit(); } }); } }, 100); }); </script>
[email_signup id="3"]
<div class="email-subscribe exp-subscribe subscribe"> <div class="alert alert-success exp-success ga-etembed-success" style="display:none;"> Great! You've signed up successfully! </div> <div class="alert alert-danger exp-error" style="display:none;"> We are experiencing an error, please try again. </div> <form name="subscribe" id="email-signup" class="email-signup-form" action="https://www.tastecooking.com/wp-admin/admin-ajax.php" method="POST" target="_top" data-event-assigned="false"> <fieldset class="form-group form-inline email-submit-group"> <label for="email-address" class="sr-only">Email Address</label> <input id="email-newsletter" type="email" placeholder="your@email.com" class="email-newsletter text email form-control" name="email" value=""> <button type="submit" value="Subscribe" name="subscribe" class="btn btn-primary email-submit-btn ga-etembed-success"> <i class="fa fa-envelope"></i> Subscribe </button> </fieldset> <small class="exp-small terms" style=""> By clicking Subscribe, I acknowledge that I have read and agree to the Penguin Random House <a href="http://www.penguinrandomhouse.com/privacy/" target="_blank">Privacy Policy</a> and <a href="http://www.penguinrandomhouse.com/terms/" target="_blank">Terms of Use</a> and agree to receive news and updates from TASTE and Penguin Random House. </small> <fieldset class="field-group checkboxes" style="display:none"> <div class="checkbox"> <label> <input type="checkbox" name="programs[]" value="505,50501,1" class="exp-checkbox" checked="checked"> <span><strong>Tastebook General</strong></span> </label> </div> <div class="checkbox"> <label> <input type="checkbox" name="programs[]" value="505,50502,1" class="exp-checkbox" checked="checked"> <span><strong>Tastebook Promo</strong></span> </label> </div> </fieldset><!-- /.checkboxes --> <input type="hidden" name="data_acq_code" value="TASTE_POPUP_STATIC_ONGOING" /> <input type="hidden" name="data_programs" value="50501|505,50502|505" /> <input type="hidden" name="form_id" value="3" /> <input type="hidden" name="partner" value="" /> <input type="hidden" name="action" value="crown_email_signup_submit" /> <input type="hidden" name="ref_url" value="" /> </form> </div> <script> jQuery(document).ready(function () { var unassigned_forms; setInterval( function() { //Check for unassigned forms var forms = jQuery( '.email-signup-form' ); unassigned_forms = false; forms.each( function( index ) { if ( jQuery( this ).attr( 'data-event-assigned' ) === 'false' ) { unassigned_forms = true; } }); if ( unassigned_forms ) { forms.off( 'submit' ).on( 'submit', function ( e ) { forms.attr( 'data-event-assigned', 'true' ); e.preventDefault(); // Basic email validation var email = jQuery(e.target).find('.email-newsletter').val(), valid_email = false, groupEl = jQuery(e.target).closest('.email-subscribe'); if ( !!email && typeof(email) === "string" ) { var email_array = email.split('@'); if ( email_array.length === 2 ) { if ( email_array[1].split('.').length > 1 ) { valid_email = true; } } } if ( valid_email ) { jQuery('.alert-danger').hide(); // Show loading gif groupEl.find('.email-signup-form').hide(); groupEl.find('.email-submit-loading').show(); // Populate ref_url jQuery(this).find('input[name="ref_url"]').val(window.location.href); // Generate Payload var payload = jQuery(this).serializeArray(); jQuery.ajax({ url: jQuery(this).attr('action'), type: 'POST', data: payload, success: function (data) { // Hide loading spinner groupEl.find('.email-signup-form').show(); groupEl.find('.email-submit-loading').hide(); // Display success msg var target = jQuery(e.target); jQuery(e.target).hide(); jQuery(e.target).parent().find('.alert-success').show(); jQuery(e.target).parent().find('#downloadbtn').show(); }, fail: function (err) { // Hide loading spinner groupEl.find('.email-signup-form').show(); groupEl.find('.email-submit-loading').hide(); // Display failure msg var target = jQuery(e.target); jQuery(e.target).hide(); jQuery(e.target).parent().find('.alert-danger').show(); } }); } else { groupEl.find('.alert-danger').html('Please enter a valid email address.').show(); } }); forms.off( 'keypress' ).on( 'keypress', function ( e ) { if ( e.which === 13 ) { e.preventDefault(); jQuery( this ).submit(); } }); } }, 100); }); </script>