0 Comments Posted in:

This is the third part in a mini-series of CSS list styling techniques. We've seen how to style striped lists in CSS and how to style comma seprated lists. This time we'll see how to style a list of social media SVG icons which was something else I wanted to create for my needed for my blog rewrite.

Here's what we'll try to make:

image

The HTML

Let's see the HTML we'll be styling first. I'm going to use the SVG icons from simple icons. It's just a regular unordered list with each item containing a link with an SVG image inside it:

<ul class="social-media-list">
    <li><a href="https://twitter.com/mark_heath"><img src="https://unpkg.com/[email protected]/icons/twitter.svg" alt="Twitter" title="Twitter"></a></li>
    <li><a href="https://github.com/markheath"><img src="https://unpkg.com/[email protected]/icons/github.svg" alt="GitHub" title="GitHub"></a></li>
    <li><a href="https://www.pluralsight.com/author/mark-heath"><img src="https://unpkg.com/[email protected]/icons/pluralsight.svg" alt="Pluralsight" title="Pluralsight"></a></a></li>
    <li><a href="https://www.youtube.com/channel/UChV2-HyJ9XzsKLQRztd7Pmw"><img src="https://unpkg.com/[email protected]/icons/youtube.svg" alt="YouTube" title="YouTube"></a></li>
    <li><a href="https://stackoverflow.com/users/7532/mark-heath"><img src="https://unpkg.com/[email protected]/icons/stackoverflow.svg" alt="Stack Overflow" title="Stack Overflow"></a></li>
</ul>

Sizing the icons

Currently it will look a real mess as we haven't constrained the size of the icons yet. So let's style the images first. I want them to be in rounded rectangles so I'll set a border-radius and give them some padding so there is a bit of space inside the rectangle around the icon. These icons have a transparent background so I'll give them a background-color. And I've specified the width and height I want for each icon:

ul.social-media-list img {
    padding: 5px;
    border-radius: 5px;
    background-color: lightblue;
    width: 36px;
    height: 36px;
}

Now we have something that looks like this:

image

Resetting the list styling

We've still got the default list styling complete with indentation and bullet points, so we need to reset the styling for our list, using list-style-type:none to get rid of the bullet points, and removing the margin and padding.

ul.social-media-list {
    list-style-type: none;
    margin: 0;
    padding: 0;

Displaying list items horizontally

I also want the icons to appear horizontally so I set the list items to display as inline-block:

ul.social-media-list li {
    display: inline-block;
}

Now we're getting very close. It currently looks like this:

image

Eliminating space between list items

Now I just had one slight problem. The gap between the icons was about a pixel or two larger than I wanted. But where was this gap coming from? It turns out that the browser is rendering a single whitespace character between each icon. There are a bunch of ways you can get round that discussed in the answers to this StackOverflow question

I decided I would use the option that seemed simplest and compatible with most browsers, which was to set the font-size to 0 pixels on the unordered list.

ul.social-media-list {
    list-style-type: none;
    margin: 0;
    padding: 0;
    font-size: 0px; /* eliminate space between li */
}

That eliminates all space between icons:

image

Now we can control the exact spacing we want by adding some margin to the list items (or images, either would work). I've just added 2 pixels:

ul.social-media-list li {
    display: inline-block;
    margin: 2px;
}

Hover over effect

Finally, I'd like a hover over effect to help the user realize these are buttons they can click. We can use the CSS :hover selector on the images to change the background-color. And if you wanted to get fancy you could also increase their size or rotate them or something here as well.

ul.social-media-list img:hover {
    background-color: #63D1F4;
}

Hover over tooltips

You'll notice also that in the HTML I specified both a title and an alt tag for each image. By providing a title, that gives me a hover-over tool-tip, which would be useful for people who might not know what all the icons were for.

Changing the foreground color?

You'll notice that in this example the icons are black. That's because the actual SVG itself is using a black brush. I had hoped that I could use a CSS style or even some JavaScript to update this as well, but it turns out that if you use an img tag pointing at an SVG file, the elements in that SVG don't appear in your DOM (see this StackOverflow answer).

I wanted white icons, so the simplest solution was for me to make my own copies SVGs and insert fill="white" on each path element.

<path fill="white" d="M12 .297c-6.63 ...

Obviously this still doesn't allow me to change the foreground color on hover over. To do that, I'd need to put the SVG inline in my page or use <object> or <embed> tags instead of <img>. But since I just wanted white icons this works fine for me:

image

Try it yourself

As usual I've put an example on codepen so feel free to experiment with this and customize it for your needs.


0 Comments Posted in:

I recently blogged about how to style striped lists in CSS. This time, I want to look at how to style a comma separated list. This was another feature I needed for my blog rewrite in order to show the list of categories each post was in.

Suppose I have the following HTML containing list of categories:

Posted in:
<ul class="comma-list">
  <li>Azure</li>
  <li>CSS</li>
  <li>C#</li>
</ul>
(8th Jan 2018)

By default that will look like this:

image

We want to get this all onto one line with commas between the categories. So first of all we'll reset the default styling by turning off the list-style and setting the padding to 0. We'll also set display: inline so that it gets rendered on the same line as "Posted in:".

.comma-list {
  display: inline;
  list-style: none;
  padding: 0px;
}

We'll also need to set the list items to display: inline to get everything onto a single line

.comma-list li {
  display: inline;
}

Now it looks like this:

image

We're getting close now, but of course there are no commas between items. We can insert them by using the CSS ::after selector to place a comma (and a space) after every list item:

.comma-list li::after {
  content: ", ";
}

This gives us almost what we need, but now we have a trailing comma after the last category:

image

We can get rid of the trailing comma by combining the ::after selector with the :last-child selector:

.comma-list li:last-child::after {
    content: "";
}

And we get the desired effect:

image

Again, I'm sure this is all very basic for CSS experts, but it was new to me. You can play with a full example on CodePen.


0 Comments Posted in:

In this post I'll run through the steps involved with creating and trying out Durable Functions in the Azure Portal. This is a great way to experiment if you don't want to (or can't) install the development environment locally.

1. Create a Function App

First you need to create a new function app in the usual way. The consumption plan is fine. In function app settings, set the runtime version to beta (I'm not sure that's required for durable functions, but I needed it in order to be offered the durable functions templates):

image

2. Install the Durable Functions Extension

To use durable functions we need the Durable Functions Extension, and the easiest way to do that is to create a function using one of the Durable Functions templates. Start off by clicking the + icon to create a new function:

image

If it takes you to the quickstart, choose "create your own custom function":

image

Choose "Durable Functions" in the "scenario" dropdown

image

Now you will be prompted Install the Durable Functions Extension:

image

It takes a few minutes to install, but once it's done we can continue to create a function using one of the Durable Functions templates.

3. Create an orchestration starter function.

Let's start off by using the HTTP Starter template, which is just a regular Azure Function that is able to kick off a new Durable Functions orchestration. I'll call mine HttpStarterFunction

image

The sample code it generates is very generic. It lets us pass in the name of the orchestrator function as a parameter. And we can post any data that we want to send to the orchestrator in the request body. Obviously in a real-world application you'd likely have functions that specifically trigger a single orchestration.

The DurableOrchestrationClient binding allows us to start a new orchestration with StartNewAsync, and we use the helpful CreateCheckStatusResponse function to return a JSON object containing the URIs we can use to query the status of the orchestration we've started.

image

4. Create an orchestrator function

We don't have any orchestrations to actually start with our starter, so let's create an orchestrator function. We'll use the orchestrator template:

image

I'll call it OrchestratorFunction:

image

This sample orchestration is going to call the same activity function three times, with different inputs ("Tokyo", "Seattle", "London"). The activity is called "Hello" and takes a string input.

image

5. Create an activity function

Next we need to create our activity function. Again there's a template for that:

image

But this time we must take care to name it with the name the name the orchestrator function is expecting ("Hello"):

image

The code for our sample activity is trivial. It takes a string and returns a string, which is fine for demo purposes. Obviously a real-world activity function would be doing something a bit more complex.

image

6. Start an orchestration

To test our orchestrator in the portal, we'll need to go back to our starter function We can click the "Test" tab, and put "OrchestratorFunction" in as the function name we want to call:

image

Now it's just a matter of clicking "Run". We'll get a 202 Accepted that gives us some JSON with information about the orchestration that was started.

image

In the JSON we get the id of the orchestration, plus a bunch of URIs we can use to check on the status. Something like this:

{"id":"6b749f72e73443d0bc84d7bb53a6a79f",
  "statusQueryGetUri": "https://durable-functions-test.azurewebsites.net/runtime/webhooks/DurableTaskExtension/instances/6b749f72e73443d0bc84d7bb53a6a79f?taskHub=DurableFunctionsHub&connection=Storage&code=3vB2Qm8yQbWosqreTspvaSfUerCpcRaMUXiCq8rfzabcJN22R88jTQ==",
  "sendEventPostUri": "https://durable-functions-test.azurewebsites.net/runtime/webhooks/DurableTaskExtension/instances/6b749f72e73443d0bc84d7bb53a6a79f/raiseEvent/{eventName}?taskHub=DurableFunctionsHub&connection=Storage&code=3vB2Qm8yQbWosqreTspvaSfUerCpcRaMUXiCq8rfzabcJN22R88jTQ==",
  "terminatePostUri": "https://durable-functions-test.azurewebsites.net/runtime/webhooks/DurableTaskExtension/instances/6b749f72e73443d0bc84d7bb53a6a79f/terminate?reason={text}&taskHub=DurableFunctionsHub&connection=Storage&code=3vB2Qm8yQbWosqreTspvaSfUerCpcRaMUXiCq8rfzabcJN22R88jTQ=="
}

7. Query orchestration status

I just need the statusQueryGetUri one to find out if the orchestration has completed yet and get its output. I can easily call this from powershell:

Invoke-WebRequest "https://durable-functions-test.azurewebsites.net/runtime/webhooks/DurableTaskExtension/instances/6b749f72e73443d0bc84d7bb53a6a79f?taskHub=DurableFunctionsHub&connection=Storage&code=3vB2Qm8yQbWosqreTspvaSfUerCpcRaMUXiCq8rfzabcJN22R88jTQ=="

Unfortunately, I got a 404 not found! It seems like at the moment there may be a bug that causes orchestrations to intermittently fail to start. Hopefully that will be resolved soon (I've reported an issue at GitHub).

However, for the ones that did work, I was able to use the statusQueryGetUri to retrieve details of the orchestration. Since this one runs pretty quickly, it will likely already be finished by the time you query it:

{
    runtimeStatus: "Completed",
    input: null,
    output: [
        "Hello Tokyo!",
        "Hello Seattle!",
        "Hello London!"
    ],
    createdTime: "2018-01-06T11:46:23Z",
    lastUpdatedTime: "2018-01-06T11:46:28Z"
}

8. Looking behind the scenes

The Durable Functions extension uses an Azure Storage account behind the scenes to track the state of your orchestrations. So if you're troubleshooting issues it can be useful to know where to look to see what's been stored. You can use the excellent Azure Storage Explorer. Here's a view of the various tables, queues and blob containers that get created for a function app with the durable tasks extension. The most useful one is the DurableFunctionsHubHistory table, which contains an "event sourced" history of all the actions that have happened in this orchestration.

image

For the bug I was encountering there were no records at all in the DurableFunctionsHubHistory table the orchestration client had claimed to start. The orchestration ids are used as partition keys in the table, so it's easy to find rows relating to the orchestration instance you are interested in:

image

Conclusion

It is quite easy to try Durable Functions in the portal without having to set up any local development environment (although I do recommend that if you plan to experiment more with Durable Functions). Seems like there are still a few bugs to iron out at the moment, but I think Durable Functions is a very promising new feature that can greatly simplify the implementation of workflows in serverless environments.

Want to learn more about how easy it is to get up and running with Azure Functions? Be sure to check out my Pluralsight course Azure Functions Fundamentals.