Images from the second day of WordCamp Europe 2015.


1. Ryan McCue opening day 2 with his talk about the REST API.

2. WordCamp Europe attendee Miguel Arroyo using the live interpretation service.

3. Andrey Savchenko asking “You put regular expressions in your routes, why again!?” after Ryan McCue‘s talk about the REST API.

4. Kari Leigh taking pictures. Go take a look at her pictures from WordCamp Europe 2015.

5. Ryan McCue talking to friends and colleagues after his talk.

6. Jack Lenox is ready to go onto the stage right before his talk about “Theming, React and the REST API”.

7. Jack Lenox on stage during his talk about theming and the REST API.

8. Simon Dickson talking to Amelia Andersdotter and Anders Jensen-Urstad right before their talk.

9. Amelia Andersdotter and Anders Jensen-Urstad during their talk about building privacy-friendly websites.

10. Simon Dickson and Petya Raykovska working away at the sidelines.

11. WordCamp Europe attendee Luca Tumedei is asking a question at the end of a talk about privacy.

12. Jeni Tennison talking about how much you should share your data.

13. Volunteer Marina Segura fighting the hot weather in Seville during WordCamp Europe 2015.

14. WordCamp attendees/volunteers Claudio Rimann, me, Heiko Mamerow, Annette Voelckner, Michael Firnkes. Photo by Ulya Yavuz.

15. Job offers and requests posted by WordCamp Europe attendees.

16. Attendees using the entrance sign as a sun shade during the crazy hot weather in Seville at WordCamp Europe 2015.

17. Adam Silverstein during his talk about Backbone.js and WordPress.

18. Mark Forrester talking about growing WooThemes and WooCommerce.

19. An attendee taking pictures during a talk at WordCamp Europe 2015.

20. Anda Pop and Alex Ciobică enjoying a talk at WordCamp Europe 2015.

21. Siobhan McKeown and Petya Raykovska with the closing remarks after a very successful WordCamp Europe 2015.

22. Happy attendees after a weekend of WordPress.

23. A big thank you to all of the volunteers.

24. All the #wceu organizers & volunteers on stage.

25. WordCamp Europe 2015 volunteers on stage.

26. Kari Leigh giving out directions to take a group picture of all organizers and volunteers of WordCamp Europe 2015.

27. Happy organizers/volunteers after WordCamp 2015 is over.

Check out my photos from day one of WordCamp Europe 2015.

All images in this post by Florian Ziegler are licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

For the ones interested in the technical aspects of photography: All images were taken with the Fujifilm X-T1 and either the XF 14mm or the XF 35mm lens.

WordCamp Europe 2015 took place in Seville, Spain last weekend. Like last year’s event, the organization was flawless. Many thanks to everyone involved! I am already looking forward to seeing you all again in Vienna in 2016.

These are my images from day one:

1. Siobhan McKeown officially starting WordCamp Europe 2015 with the opening remarks.

2. Attendees need to sit on the floor due to huge interest in talks taking place in room 2.

3. Simon Dickson moderating the talks in room 2 in the morning of the first day of wceu.

4. Rian Rietveld during her talk: “The Accessibility-Ready Tag for Your Theme: Why and How”.

5. WordCamp attendees listening to Rian Rietveld’s talk about accessibility in WordPress.

6. Adrian Zumbrunnen and Pascal Birchler waiting to go on stage for their short talks.

7. Pascal Birchler on stage during his talk “Centralizing WordPress Professionals”.

8. Attendees are obviously multitasking while listening to talks in room 1.

9. Silvan Hagen sporting the right outfit for the crazy hot temperatures during WordCamp Europe 2015 in Seville.

10. Bryce Adams talking about how he built a WordPress-powered SaaS in 3 Days.

11. Andrea Gandino listening attentively to what’s happening on stage.

12. Bryce Adams had the most entertaining slides in his talk about creating a SaaS with WordPress.

13. Mika Epstein talking about working with hosting companies.

14. Attendees getting their WordCamp t-shirts.

15. Command center to control the live stream.

16. Ibon Azkoitia Velasco and Rocio Valdivia, happy volunteers/organizers at #wceu 2015

17. Volunteers, easily spotted by their orange crew shirts, giving out WordCamp t-shirts to attendees.

18. Iain Tailor trying on a WordCamp branded hat. I think you made the right choice there, Iain. :)

19. Nikolay Bachiyski talks about WordPress security principles. It was later announced by Matt Mullenweg that Nikolay was named “Security Czar” for the WordPress Project.

20. Lunch time at WordCamp Europe 2015.

21. Interpreter booth: All talks were interpreted live into Spanish.

22. Attendees fill the room right before Matt Mullenweg’s Q&A session.

23. Matt Mullenweg on stage during his Q&A session.

24. Caspar Hübinger asking Matt what it would take to prioritize the improvement of rossetta sites and in general.

25. Matt Mullenweg enjoying the Q&A session at WordCamp Europe 2015.

26. Camera operators capturing the event for the live stream. All talks will also be available on

27. Thomas Brühl taking pictures during the Q&A session.

28. Mario Peshev taking a well deserved break from his volunteering duties during Matt’s Q&A session.

29. Full house during Matt Mullenweg’s Q&A session at WordCamp Europe 2015.

30. Zeev Suraski brought this one of a kind, golden PHP elephant to WordCamp Europe 2015.

31. Mark Jaquith talking about “Ethics and WordPress Development”.

32. Aaron Jorbin talking about “The Future of WordPress Build Tools”.

33. View into the interpreter booth in room 2 of WordCamp Europe 2015.

Update: Images from day 2 are up!

All images in this post by Florian Ziegler are licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

For the ones interested in the technical aspects of photography: All images were taken with the Fujifilm X-T1 and either the XF 14mm or the XF 35mm lens.

We have been in Seville for almost two weeks now. Unfortunately I didn’t have much time to explore the city with my camera, so the yield of pictures is pretty minimum at this point. I’ll still attach a some of my favorite street shots below.

Next weekend will be WordCamp – the main reason we came here in the first place. I guess I’ll document the event as I did in 2013 and 2014.

After that, we’ll have some vacation days and I hope to get some photography time in there as well.

Stay tuned and enjoy the images.

Sevilla Street Photography

Sevilla Street Photography

Sevilla Street Photography

Sevilla Street Photography

Sevilla Street Photography

Sevilla Street Photography

Sevilla Street Photography

Sevilla Street Photography

Sevilla Street Photography

Sevilla Street Photography

Sevilla Street Photography

Sevilla Street Photography

Sevilla Street Photography

CSS Tutorial: Style Table Rows To Look Like Cards

A client needed a more readable design for some of the tables on their website. The typical table styling was not cutting it, because the last column of said tables contained way more content than all the other columns. (Keep that in mind, while I use dummy content and a more generic styling in my explanation below.)

In addition, the tables were created automatically, with little influence on the composition of the tables in terms of classes, IDs or custom attributes, so using another HTML structure was not possible either.

The HTML is straightforward enough:

<table class="cards-table">
            <th>Column A</th>
            <th>Column B</th>
            <th>Column C</th>
            <th>Column D</th>

The regular table styling looks something like this:

Regular Table Layout

Figure A: Regular table layout. Again, keep in mind, that on the client’s website the last column contained much more content, than in this example.

I suggested a card-like layout for each table row, that looks something like this:

Card Layout

Figure B: Alternate, card-like table layout with more room for the last column. Each cell gets a label that corresponds to its table header.

The client liked the idea.

Let’s have a look on how to get from A to B.

(There is some SCSS sprinkled in here and there, but you can do the exact same thing with plain CSS as well.)

First, hide the table header:

thead {
    display: none;

Style the table rows to look like individual cards:

tr {
    display: block;
    margin-bottom: 1.5rem;
    padding: 1rem 0.5rem 0.5rem 1rem;
    background-color: transparentize( white, 0.15 );
    box-shadow: 0 0 1rem transparentize( black, 0.9 );

On to the individual table cells, basic styling first:

td {
    display: inline-block;
    margin: 0 0.5rem 0.5rem 0;
    padding: 0.5rem;
    text-align: left;
    background-color: white;
    border: 1px solid transparentize( #58C25F, 0.5 );

Now let’s add the labels. I decided to use pseudo-elements:

td:before {
    float: left;
    margin: -0.5rem 0.5rem -0.5rem -0.5rem;
    padding: 0.625rem 0.5rem 0.625rem;
    font-size: 0.75em;
    font-weight: bold;
    background: transparentize( #58C25F, 0.9 );
    color: #58C25F;

At this point the pseudo-element still has no content.

If the composition of your table is always the same, you might just define the label content row by row, directly in your stylesheet:

td:nth-child(2):before {
    content: "Column 2 Label: ";

For my use case I needed the labels to be dynamic:

  • It had to work for variable table layouts and
  • with multiple tables on the same page.

I decided to use a data attribute as the content source for the pseudo-element.

First, create a “data-label” attribute and attach it to every <td> with a bit of JavaScript/jQuery:

var tables = $('.cards-table');

// Create an array containing all table headers
var table_headers = [];
tables.each(function() {
    var th = [];
    $(this).find('thead th').each(function() {

// Add a data-label attribute to each cell
// with the value of the corresponding column header
// Iterate through each table
tables.each(function(table) {
    var table_index = table;
    // Iterate through each row
    $(this).find('tbody tr').each(function() {
        // Finally iterate through each column/cell
        $(this).find('td').each(function(column) {
            $(this).attr('data-label', table_headers[table_index][column]);

Then, finally display the content using the attr() CSS function:

td:before {
    content: attr(data-label) ": ";

If you remember, the last column needed more space. It should span the whole width of the card.

At this point you could either use the :last-child selector, to target the last column/cell in a row, or, to make it even more flexible, use an attribute selector to target a cell, depending on its column header:

td[data-label="Column D"] {
    display: block;
    float: none;

    &:before {
        display: block;
        margin-right: -0.5rem;
        margin-bottom: 0.5rem;
        float: none;

Bonus: To clean it up even more, you can just hide empty cells:

td:empty {
    display: none;

And that’s it!

Did I mention, that this is all completely responsive?

I hope you found this post useful. :)

You can find a complete code example on CodePen.