If you can derive all decorable classes from some base class, then you can try to store decorators in that base class and make its info recoverable. Here is sample code that is guaranteed to contain some errors, but you can get the idea.
public class Decorable
{
Dictionary<Type,object> decors = new Dictionary<Type,object>();
public void AddDecorator<D>(D decor) { decors[typeof(D)] = decor; }
public D GetDecorator<D>()
{
object value;
if (decors.TryGetValue(typeof(D), out value))
return (D)value;
else
return default(D);
}
}
public class Decorator<T> where T: class, Decorable
{
private readonly T _instance;
public Decorator(T instance)
{
_instance = instance;
instance.AddDecorator(this);
}
public T Instance
{
get { return _instance; }
}
public object AdditionalInformation { get; set; }
}
// use it like this
Decorator<MyClass> myDecor = myObj.GetDecorator<Decorator<MyClass>>();
If you cannot derive, then you must store info in some static class. But, as wcoenen commented, you would need to clear that info or you'd get memory leaks. Clearing is error prone and not always possible, so it's better to go with the first approach. For example (not thread safe, you must add locking if you plan to use it in multithreaded apps):
static public class Decorators
{
static Dictionary<object,Dictionary<Type,object>> instance = new Dictionary<object,Dictionary<Type,object>>();
public static void AddDecorator<T,D>(this T obj, D decor)
{
Dictionary<Type,object> d;
if (!instance.TryGetValue(obj, out d))
{
d = new Dictionary<Type,object>();
instance.Add(obj, d);
}
d[typeof(D)]=decor;
}
public static D GetDecorator<T,D>(this T obj)
{
// here must be double TryGetValue, but I leave it to you to add it
return (D) instance[obj][typeof(D)];
}
public static T ClearDecorators(this T obj) { instance.remove(obj); }
}
// Decorator<T> code stays the same, but without type constraint
Methods for Aligning Flex Items along the Main Axis
As stated in the question:
To align flex items along the main axis there is one property: justify-content
To align flex items along the cross axis there are three properties: align-content
, align-items
and align-self
.
The question then asks:
Why are there no justify-items
and justify-self
properties?
One answer may be: Because they're not necessary.
The flexbox specification provides two methods for aligning flex items along the main axis:
- The
justify-content
keyword property, and
auto
margins
justify-content
The justify-content
property aligns flex items along the main axis of the flex container.
It is applied to the flex container but only affects flex items.
There are five alignment options:
flex-start
~ Flex items are packed toward the start of the line.
![enter image description here](https://i.stack.imgur.com/YOzeU.png)
flex-end
~ Flex items are packed toward the end of the line.
![enter image description here](https://i.stack.imgur.com/13Z1u.png)
center
~ Flex items are packed toward the center of the line.
![enter image description here](https://i.stack.imgur.com/oKi7M.png)
space-between
~ Flex items are evenly spaced, with the first item aligned to one edge of the container and the last item aligned to the opposite edge. The edges used by the first and last items depends on flex-direction
and writing mode (ltr
or rtl
).
![enter image description here](https://i.stack.imgur.com/0mQqd.png)
space-around
~ Same as space-between
except with half-size spaces on both ends.
![enter image description here](https://i.stack.imgur.com/u4BH6.png)
Auto Margins
With auto
margins, flex items can be centered, spaced away or packed into sub-groups.
Unlike justify-content
, which is applied to the flex container, auto
margins go on flex items.
They work by consuming all free space in the specified direction.
Align group of flex items to the right, but first item to the left
Scenario from the question:
making a group of flex items align-right (justify-content: flex-end
)
but have the first item align left (justify-self: flex-start
)
Consider a header section with a group of nav items and a logo. With
justify-self
the logo could be aligned left while the nav items stay
far right, and the whole thing adjusts smoothly ("flexes") to
different screen sizes.
![enter image description here](https://i.stack.imgur.com/D3Vnv.png)
![enter image description here](https://i.stack.imgur.com/Um8DM.png)
Other useful scenarios:
![enter image description here](https://i.stack.imgur.com/qLzgU.png)
![enter image description here](https://i.stack.imgur.com/HtaOc.png)
![enter image description here](https://i.stack.imgur.com/M2WkZ.png)
Place a flex item in the corner
Scenario from the question:
- placing a flex item in a corner
.box { align-self: flex-end; justify-self: flex-end; }
![enter image description here](https://i.stack.imgur.com/BtbfK.png)
Center a flex item vertically and horizontally
![enter image description here](https://i.stack.imgur.com/lV9a0.png)
margin: auto
is an alternative to justify-content: center
and align-items: center
.
Instead of this code on the flex container:
.container {
justify-content: center;
align-items: center;
}
You can use this on the flex item:
.box56 {
margin: auto;
}
This alternative is useful when centering a flex item that overflows the container.
Center a flex item, and center a second flex item between the first and the edge
A flex container aligns flex items by distributing free space.
Hence, in order to create equal balance, so that a middle item can be centered in the container with a single item alongside, a counterbalance must be introduced.
In the examples below, invisible third flex items (boxes 61 & 68) are introduced to balance out the "real" items (box 63 & 66).
![enter image description here](https://i.stack.imgur.com/3IeTy.png)
![enter image description here](https://i.stack.imgur.com/BmtRt.png)
Of course, this method is nothing great in terms of semantics.
Alternatively, you can use a pseudo-element instead of an actual DOM element. Or you can use absolute positioning. All three methods are covered here: Center and bottom-align flex items
NOTE: The examples above will only work – in terms of true centering – when the outermost items are equal height/width. When flex items are different lengths, see next example.
Center a flex item when adjacent items vary in size
Scenario from the question:
in a row of three flex items, affix the middle item to the center of the container (justify-content: center
) and align the adjacent
items to the container edges (justify-self: flex-start
and
justify-self: flex-end
).
Note that values space-around
and space-between
on justify-content
property will not keep the middle item centered in relation to the container if the adjacent items have different widths (see demo).
As noted, unless all flex items are of equal width or height (depending on flex-direction
), the middle item cannot be truly centered. This problem makes a strong case for a justify-self
property (designed to handle the task, of course).
#container {
display: flex;
justify-content: space-between;
background-color: lightyellow;
}
.box {
height: 50px;
width: 75px;
background-color: springgreen;
}
.box1 {
width: 100px;
}
.box3 {
width: 200px;
}
#center {
text-align: center;
margin-bottom: 5px;
}
#center > span {
background-color: aqua;
padding: 2px;
}
<div id="center">
<span>TRUE CENTER</span>
</div>
<div id="container">
<div class="box box1"></div>
<div class="box box2"></div>
<div class="box box3"></div>
</div>
<p>The middle box will be truly centered only if adjacent boxes are equal width.</p>
Here are two methods for solving this problem:
Solution #1: Absolute Positioning
The flexbox spec allows for absolute positioning of flex items. This allows for the middle item to be perfectly centered regardless of the size of its siblings.
Just keep in mind that, like all absolutely positioned elements, the items are removed from the document flow. This means they don't take up space in the container and can overlap their siblings.
In the examples below, the middle item is centered with absolute positioning and the outer items remain in-flow. But the same layout can be achieved in reverse fashion: Center the middle item with justify-content: center
and absolutely position the outer items.
![enter image description here](https://i.stack.imgur.com/U1eLb.png)
Solution #2: Nested Flex Containers (no absolute positioning)
.container {
display: flex;
}
.box {
flex: 1;
display: flex;
justify-content: center;
}
.box71 > span { margin-right: auto; }
.box73 > span { margin-left: auto; }
/* non-essential */
.box {
align-items: center;
border: 1px solid #ccc;
background-color: lightgreen;
height: 40px;
}
<div class="container">
<div class="box box71"><span>71 short</span></div>
<div class="box box72"><span>72 centered</span></div>
<div class="box box73"><span>73 loooooooooooooooong</span></div>
</div>
Here's how it works:
- The top-level div (
.container
) is a flex container.
- Each child div (
.box
) is now a flex item.
- Each
.box
item is given flex: 1
in order to distribute container space equally.
- Now the items are consuming all space in the row and are equal width.
- Make each item a (nested) flex container and add
justify-content: center
.
- Now each
span
element is a centered flex item.
- Use flex
auto
margins to shift the outer span
s left and right.
You could also forgo justify-content
and use auto
margins exclusively.
But justify-content
can work here because auto
margins always have priority. From the spec:
8.1. Aligning with auto
margins
Prior to alignment via justify-content
and align-self
, any
positive free space is distributed to auto margins in that dimension.
justify-content: space-same (concept)
Going back to justify-content
for a minute, here's an idea for one more option.
space-same
~ A hybrid of space-between
and space-around
. Flex items are evenly spaced (like space-between
), except instead of half-size spaces on both ends (like space-around
), there are full-size spaces on both ends.
This layout can be achieved with ::before
and ::after
pseudo-elements on the flex container.
![enter image description here](https://i.stack.imgur.com/Jjw9w.png)
(credit: @oriol for the code, and @crl for the label)
UPDATE: Browsers have begun implementing space-evenly
, which accomplishes the above. See this post for details: Equal space between flex items
PLAYGROUND (includes code for all examples above)
Best Answer
You can just add
flex: 0.5
to item container: